1.grep | xargs mv

1.grep | xargs mv

1つのディレクトリにそのようなファイルがいくつかあります

00.01.02 0000 some filename 1.pdf
00.01.02 0000 some filename 1.txt
02.03.07 0163 another filename 2.pdf
02.03.07 0163 another filename 2.txt

特定の文字列を含むすべての txt ファイルを見つけて、この txt ファイルと対応する pdf ファイルを別のディレクトリに移動する必要があります。

これを実行する最善の方法は何ですか?

答え1

3 つのオプションがあります。基本的な考え方は次のとおりです。

  1. grep | xargs mv
  2. grep | parallel mv
  3. find -exec grep -q -exec mv

1.grep | xargs mv

使用しgrepxargs

grep -FlZ "some string" *.txt \
| xargs -0 -I{} sh -c 'echo mv "$1" "${1%.*}.pdf" some/other/directory' xargs-sh {}

grep:

  • -Fパターンではなく文字列全体に一致します
  • -l一致するファイル名のみ出力
  • -Zファイル名の間にゼロ区切り文字を出力します (ファイル名には改行文字が許可されているため、区切り文字として改行文字を使用することはできないため、これは重要です)

xargs:

  • -0ゼロ区切りのデータを読み取ります

2.grep | parallel mv

対応する PDF ファイル名を取得するには、xargsを使用してサブシェルを呼び出す必要があります。sh -c

そうする代わりに、GNU parallelクールな機能を活用することもできます!!

grep -FlZ "some string" *.txt \
| parallel -0 -j1 echo mv {} {.}.pdf some/other/directory
  • -j1一度に1つの仕事だけ
  • {}ファイル名
  • {.}拡張子なしのファイル名

3.find -exec grep -q -exec mv

もう一つの代替案として、以下を使用しますfind

find . -maxdepth 1 -name "*.txt" \
-exec grep -Fq "some string" {} \; \
-exec sh -c 'echo mv "$1" "${1%.*}.pdf" some/other/location' find-sh {} \;
  • -maxdepth 1再帰しない
  • grep -qファイル名ではなくエラー コードのみを取得する場合、2 番目は-exec最初のものが成功した場合にのみ実行されます。
  • 2 番目は基本的に最初のオプション-execと同じです。xargs
  • ファイル名を渡さないので、ゼロ区切りの出力を行う必要はありませんfind

各オプションについて、echo出力に満足している場合は を削除します。

答え2

問題を細分化します。

「現在のディレクトリ内で、特定の文字列を含むすべてのテキスト ファイルを見つける必要があります」。

grep -F "text string just as written (no regex)" *.txt

「私はファイル名これらのファイルの

grep -l -F "text string" *.txt

「これらのファイルごとに...」

for...each はwhile/do/done、ファイルリストを渡す構文を使用して実行します。各ファイルに対して、以下を実行できます。何か変数にアクセスできるようになります$file:

grep -l -F "text string" *.txt \
| while IFS= read -r file ; do
...something...
done

「何か」とは

「...txt ファイルと対応する pdf ファイルを移動します...」

したがって、「.txt」を除いたベース名が必要です。

BASE=$( basename ${file} .txt )

最後にすべてをまとめると次のようになります。

grep -l -F "text string" *.txt \
| while IFS= read -r file ; do \
    BASE=$( basename ${file} .txt )
    mv ${BASE}.txt /some/other/dir
    mv ${BASE}.pdf /some/other/dir
done

(注意:これは、各ファイルパスがないため、basenameパスが削除されてしまいます。

答え3

parallelコマンドがない場合は、xargs以下の2つを実行します

grep -l 'search string' *.txt | xargs -I {} basename {} .txt | xargs -I {} cp {}.pdf /destination-directory

関連情報