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

相关内容