我在一个目录中有一些类似的文件
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