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

  • -0讀取零分隔數據

2.grep | parallel mv

xargs需要使用呼叫子shellsh -c才能取得對應的pdf檔名。

除了這樣做之外,您還可以利用一些GNU parallel很酷的功能!

grep -FlZ "some string" *.txt \
| parallel -0 -j1 echo mv {} {.}.pdf some/other/directory
  • -j1一次只有一份工作
  • {}檔案名稱
  • {.}不含副檔名的檔名

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僅獲取錯誤代碼而不是文件名,第二個-exec只有在第一個成功時才會運行。
  • 第二個選項-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以下兩個操作

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

相關內容