存在するこのブログ単一のファイルをインポートする次の構造のbashスクリプト( "snippet"セクション)が見つかりました.bash_profile
。
if [ -d ~/.bash_profile.d ]; then
for file in $( find ~/.bash_profile.d -type f )
do
if [ -f "$file" ]; then
source "$file"
fi
done
fi
find -type f
まず、bash演算子を使用してファイルをフィルタリングしてから再確認するのが合理的ですか-f
、それとも一種のパッチワークですか?
以下のスクリプトも同じではありませんか?
if [ -d ~/.bash_profile.d ]; then
for file in $( find ~/.bash_profile.d -type f )
do
source "$file"
done
fi
そうでなければ違いは何ですか?
ベストアンサー1
このコードにはいくつかの問題がありますが、驚くべきことに、ダブルファイルスキャンはそのうちの1つではありません。
まず、@EricRenoufが示すように、$()
周囲の建設が間違っていました。find
正しい方法は、次のようなものを使用することです。
while read filename
do
source $filename
done < <(find ....)
サブシェルからfindを呼び出し、ファイル名をfilename
メインシェルの変数として読み込みます(これはfind | while read x
アイデアですが、残念ながら移植可能ではありません)。
第二に、-d
ディレクトリテストは冗長です。find
ディレクトリが存在しないとファイルが見つからないため、存在するかどうかをテストする必要はありません。
ただし、パラメータはパラメータとまったく同じものを-type f
テストしません。find
POSIXには次のものがあります-f
test
説明するについてtest
:
- F パス名
もし本当だパス名通常のファイルとして解決される既存のディレクトリエントリ。パス名が解決できない場合、またはパス名が非正規ファイルの既存のディレクトリエントリとして解決された場合はFalseを返します。
そしてこれを持って説明するについてfind
:
-タイプ 氏
ファイルの種類が次の場合、デフォルト項目はtrueと評価する必要があります。氏、どこ氏ブロック特殊ファイル、文字特殊ファイル、ディレクトリ、シンボリックリンク、FIFO、一般ファイルを表す 'b'、'c'、'd'、'l'、'p'、'f'、または 's' です.またはそれぞれソケットです。
したがって、「解析できない」汎用ファイルがある場合はtest -f
失敗しますが、find -type f
成功するファイルが存在します。これを達成する1つの方法は、読み取ることはできますがアクセスできないディレクトリにファイルを配置することです。
wouter@gangtai:~$ ls -ld foo
drw-r--r--. 2 wouter wouter 4096 apr 1 18:38 foo
wouter@gangtai:~$ find foo -type f | while read file; do if [ -f $file ]; then echo $file tests -f; else echo $file does not test -f; fi; done
foo/bar does not test -f
wouter@gangtai:~$ ls -l foo
ls: cannot access 'foo/bar': Permission denied
total 0
-????????? ? ? ? ? ? bar
これタイプファイルが保存されているディレクトリに対する権限があるが権限がない場合は、ファイルr
(ディレクトリ、一般ファイル、またはその他のファイル)に対する権限を検出できます。x
ただし、これを「解決する」(つまり、stat()
そのファイルの関数の1つを呼び出す)にはx
、そのディレクトリの権限ビットが必要です。
もちろん、シェルスクリプトでこれらのテストが.bashrc
有効かどうかは別の問題です。いいえと言いたいです。しかし、これは両方のテストが同じであるという意味ではなく、はいこの違いの状況はい重要...