我在一個目錄中有一些類似的文件
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 個選擇,基本想法是:
grep | xargs mv
grep | parallel mv
find -exec grep -q -exec mv
1.grep | xargs mv
使用grep
和xargs
:
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