1.grep | xargs mv

1.grep | xargs mv

ディレクトリにこのようなファイルがあります

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:

  • -00で区切られたデータの読み取り

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つのタスク
  • {}ファイル名
  • {.}拡張子のないファイル名

三。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

関連情報