for ループでは Find コマンドが機能しません。

for ループでは Find コマンドが機能しません。

ファイル名のリストがあり、パスを取得できるようにコマンドを見つけるためにファイルを1つずつ提供したいと思います。 forループを使用し、catコマンドを使用して変数のすべてのファイル名を取得し、変数を1つずつfindコマンドに渡しましたが、機能しません。誰でも私を案内できますか?

for f in $(cat filelist.txt)
do 
find /home/abc/ -type f -name "$f"
done;

エラーは発生しませんが、出力も取得できず、出力を変数に入れようとしましたが、運がありません。

ベストアンサー1

各行に保存されているファイルの1つの名前を持つファイルを見つけるには、sをfilelist.txt使用する簡単な方法があります。zshglobbing

names=( ${(f)"$(<filelist.txt)"} ) &&
  (( $#names )) &&
  print -rC1 -- /home/abc/**/${(~j[|])names}(D.)

あなたのアプローチがうまくいかない理由は何の問題もありませんが、すぐには明確ではありません。

  • では、bash引用されていないコンテンツペア(zshでのみ分割)$(cat filelist.txt)のコンテンツに対してSplit + globを呼び出しますfilelist.txt。デフォルト$IFS(分割セクションの場合)を使用すると、改行だけでなくスペースやタブでも分割されます。したがって、その中に行がある場合は、呼び出されたファイルではなく、呼び出されたファイルと呼び出されたファイルをmy file.txt探します。myfile.txtmy file.txt
  • file*というファイルがある場合filelist.txt全体的な状況セクションは、スクリプトが呼び出されるディレクトリのファイルのリストに展開されます。
  • -name '*'名前付きファイルも検索されませんが、*渡されたコンテンツは-nameパターンとして処理されるため、すべてのファイルが報告されます。ワイルドカード演算子を無効にするには、エスケープ[とwithが?必要です。*\\

今、あなたの質問は次のとおりです。

  • filelist.txtLF の代わりに CRLF 区切り文字を使用する MSDOS テキスト形式です。これを実行してdos2unix問題を解決します。
  • ファイルパスfilelist.txt(たとえばdir/file.txt)があります。-nameファイル名のみが一致するため、絶対一致しません。

ここではループの代わりにGNUを使用できますxargs

xargs -rd'\n' -a filelist.txt -I NAME find /home/abc/ -name NAME -type f

ただし、これはまだ各ファイル名全体を把握することを意味し、/home/abc/これは非効率的です。

代わりに、次のようにすることができます。

xargs -rd'\n' -n200 -a <(sed 's/[*?\\[]/\\&/g' filelist.txt) sh -c '
  for name do
    set -- -o -name "$name"
    shift
  done
  shift
  find /home/abc/ \( "$@" \) -type f' sh

find /home/abc/ \( -name name1 -o -name name2... \) -type f1回の呼び出しで最大200の名前を呼び出すことができます。findつまり/home/abc、 1 つだけ呼び出すほど良くはありませんがはるかにzsh良いです。

sedまた、名前にはエスケープされたワイルドカード文字を使用します。そこも通れますdos2unix

おすすめ記事