回答
readarray
が言及されていないことに驚いています。<<<
演算子:
$ touch oneword "two words" $ readarray -t files <<<"$(ls)" $ for file in "${files[@]}"; do echo "|$file|"; done |oneword| |two words|
<<<"$expansion"
構文を使用すると、新しい行を含む変数を次のように配列に分割することもできます。 :
$ string=$(dmesg) $ readarray -t lines <<<"$string" $ echo "${lines[0]}" [ 0.000000] Initializing cgroup subsys cpuset
readarray
はBashに何年も存在しているので、これはおそらく標準的な方法です。これはBashで。
回答
Afaikfindには必要なものがすべて揃っています。
find . -okdir diff {} /some/other/path/{} ";"
findは、プログラムを節約的に呼び出すために自動的に処理します。-okdirは、diffの前にプロンプトを表示します(はい/いいえでよろしいですか)。
シェルは含まれず、グロビング、ジョーカー、 pi、pa、po。
補足として:findをfor / while / do / xargsと組み合わせると、ほとんどの場合、y間違っている。 🙂
コメント
回答
任意のファイル(任意の特殊文字を含む)をループします。 完全に安全な検索(ドキュメントについてはリンクを参照):
exec 9< <( find "$absolute_dir_path" -type f -print0 ) while IFS= read -r -d "" -u 9 do file_path="$(readlink -fn -- "$REPLY"; echo x)" file_path="${file_path%x}" echo "START${file_path}END" done
コメント
-
-d ''
に言及していただきありがとうございます。 '$'\0'
が''
と同じであることに気づきませんでしたが、あります。良い解決策でもあります。 - findとwhileの分離が好きです、ありがとう。
回答
ここで明らかなzsh
ソリューションについて誰も言及していないことに驚いています:
for file (**/*.csv(ND.)) { do-something-with $file }
((D)
隠しファイルも含める場合、(N)
一致しない場合にエラーを回避する場合、(.)
を通常のファイルに制限します。)
bash4.3
以降では、部分的にもサポートされるようになりました:
shopt -s globstar nullglob dotglob for file in **/*.csv; do [ -f "$file" ] || continue [ -L "$file" ] && continue do-something-with "$file" done
回答
スペースを含むファイル名は、コマンドラインで複数の名前のように見えます。 “ファイルの名前が「HelloWorld.txt」の場合、差分行は次のように展開されます。
diff Hello World.txt /some/other/path/Hello World.txt
これは4つのファイル名のように見えます。引数の前後の引用:
diff "$file" "/some/other/path/$file"
コメント
- これは役に立ちますが、そうではありません'問題を解決します。ファイルが複数のトークンに分割されている場合がまだあります。
- この回答は誤解を招く恐れがあります。問題は
for file in `find . -name "*.csv"`
コマンドです。Hello World.csv
というファイルがある場合、file
は./Hello
に設定され、次にWorld.csv
。$file
を引用すると'役に立ちません。
回答
二重引用符はあなたの友達です。
diff "$file" "/some/other/path/$file"
それ以外の場合、変数の内容は単語分割されます。
コメント
- これは誤解を招く恐れがあります。問題は
for file in `find . -name "*.csv"`
コマンドです。
、file
は./Hello
に設定され、次にWorld.csv
。$file
を引用すると'役に立ちません。
回答
bash4では、組み込みのmapfile関数を使用して、各行を含む配列を設定し、この配列を反復処理することもできます。
$ tree . ├── a │ ├── a 1 │ └── a 2 ├── b │ ├── b 1 │ └── b 2 └── c ├── c 1 └── c 2 3 directories, 6 files $ mapfile -t files < <(find -type f) $ for file in "${files[@]}"; do > echo "file: $file" > done file: ./a/a 2 file: ./a/a 1 file: ./b/b 2 file: ./b/b 1 file: ./c/c 2 file: ./c/c 1
回答
値のスペースは、単純なforループ構造で回避できます
for CHECK_STR in `ls -l /root/somedir` do echo "CHECKSTR $CHECK_STR" done
ls -l root / somedir cスペースを含むファイルを保持します
スペースを含むファイルの上に出力
この出力を回避するための簡単な解決策(二重引用符に注意)
for CHECK_STR in "`ls -l /root/somedir`" do echo "CHECKSTR $CHECK_STR" done
スペースを入れてファイルを出力する
bashで試してみました
コメント
- 「ファイルをループする」–それが質問の内容です。ソリューションは、全体
ls -l
の出力を一度に出力します。これは、echo "CHECKSTR `ls -l /root/somedir`"
と実質的に同等です。
time find -type f -exec cat "{}" \;
とtime find -type f -print0 | xargs -0 -I stuff cat stuff
を比較してください。xargs
バージョンは、10000個の空のファイルを処理するときに11秒高速でした。ほとんどの場合、find
を他のユーティリティと組み合わせるのは間違っていると主張するときは注意してください。-print0
と-0
は、スペースではなくゼロバイトをアイテムの区切り文字として使用して、ファイル名のスペースを処理するためにあります。time find -type f -exec cat {} +
は0.1秒かかりました。 s。 "間違っている"と"あなた'間違っている"、特にスミリーで飾られている場合。たとえば、あなたはそれを間違えましたか? ;)ところで、ファイル名のスペースは上記のコマンドでは問題なく、一般的に見つかります。カーゴカルトプログラマー?ちなみに、findを他のツールと組み合わせるのは問題ありませんが、ほとんどの場合、xargsだけが不要です。+
は非常に高速です。xargs
をこのように使用するこの機能は、多くの場合に役立つため、カーゴカルトプログラマーとは言いません。私はUnix哲学にもっと同意します:一つのことをしてそれをうまくやりなさい(仕事を成し遂げるためにプログラムを別々にまたは組み合わせて使う)。find
はそこに細い線を歩いています。