次のタスクを実行するbashスクリプトがあります。
for src in $(find -H "$DOTFILES_ROOT" -maxdepth 2 -name '*.sym' -not -path '*.git*')
do
dst="$HOME/$(basename "${src%.*}")"
link_file "$src" "$dst"
done
私のスクリプトでshellcheckを実行しましたが、結果が返されました。
For loops over find output are fragile. Use find -exec or a while read loop.
私はそれを読んで理解し、それは私にとって理解されています。
find -H "$(pwd)" -maxdepth 2 -name '*.sym' -not -path '*.git*' -exec echo {} \;
しかし、forループで変数を使用して機能させる方法はわかりません。
ベストアンサー1
ループの変数はとfor
です。ループ内のファイルで指定されたパス名から計算されます。src
dst
src
find
dst
src
ループはfind -exec
次のコマンドに変換できます。
find -H "$DOTFILES_ROOT" -maxdepth 2 -type d -name '.git' -prune -o \
-type f -name '*.sym' -exec sh -c '
link_file "$1" "$HOME/$( basename "${1%.*}" )"' sh {} ';'
目次-not -path '*.git*'
を見る予定がないとします。.git
これは-type d -name '.git' -prune
上記と同じコマンドですが、これらのディレクトリへの移動も停止します-prune
。find
.git
ディレクトリを消去すると、.sym
ファイルの検索が開始されます。 1つが見つかると、ループ内のコマンドが実行されます。コマンドはsh -c
(引数置換を渡し、いくつかの素晴らしいタスクを実行できるように)を通して実行され、basename
見つかったファイルのパス名は内部的に使用できます$1
。
次のように作成したように、ループを(ほぼ)マージすることもできます。
find -H "$DOTFILES_ROOT" -maxdepth 2 -type d -name '.git' -prune -o \
-type f -name '*.sym' -exec sh -c '
for src do
dst="$HOME/$( basename "${src%.*}" )"
link_file "$src" "$dst"
done' sh {} +
この場合、sh -c
スクリプトには単一のパス名ではなく複数のパス名が指定されているため(最後+
のパスのため-exec
)、そのパス名を繰り返し操作してください。
関連: