如何使用“文件”(创建应用程序的名称:Microsoft Word)的结果来搜索特定字符串?

如何使用“文件”(创建应用程序的名称:Microsoft Word)的结果来搜索特定字符串?

我正在尝试使用“文件”的结果,它返回有关我指定的文件的信息。

例如

file *.doc 'all .doc extensions

然后返回有关文件的信息,包括“创建应用程序的名称:Microsoft Word”。现在,我尝试在结果中搜索字符串“Word”。我被困在这里了。我实际上该如何做到这一点?

*这是我经过几个小时的搜索后尝试的。我只是不知道我要找什么词。请指教。

find . -type f -print0 | xargs -0 grep -lh "Microsoft Word" | xargs -I % mv % ../NewDirectory/

我认为这会在文件本身中搜索字符串“Word”并将其移动到新目录。

答案1

如果我理解正确的话,您希望将文件从当前目录及其子目录递归移动到另一个目录,但前提是该file命令将它们报告为“Microsoft Word”文件。也就是说,您对file "$filename" | grep 'Microsoft Word'产生一些输出的文件感兴趣。

一个简单的方法是冷静地处理事情并逐一处理。如果您只需要当前目录中的文件,则可以使用for循环和通配符模式:

for f in *.doc; do
  if …
done

条件是什么?我们想要测试是否Microsoft Word出现在 的输出中file "$f"。我用来file --防止名称以-.

for f in *.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
  fi
done

我们需要做的就是添加移动文件的命令。

for f in *.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
    mv -- "$f" ../NewDirectory/
  fi
done

如果您还想在子目录中查找文件,请使用**通配模式用于递归通配符。在 bash 中,需要使用 来激活shopt -s globstar(在 ksh93 中,您需要set -o globstar,而在 zsh 中,它可以开箱即用;其他 shell 缺乏此功能)。请注意,bash ≤4.2 遵循目录的符号链接。

for f in **/*.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
    mv -- "$f" ../NewDirectory/
  fi
done

请注意,所有移动的文件均以 结尾../NewDirectory/,不会创建任何子目录。如果你想重现目录树,你可以使用字符串操作结构提取文件名的目录部分并mkdir -p根据需要创建目标目录。

for f in ./**/*.doc; do
  if file "$f" | grep -s 'Microsoft Word'; then
    d="${f%/*}"
    mkdir -p ../NewDirectory/"$d"
    mv "$f" ../NewDirectory/"$d"
  fi
done

您可能更喜欢解析输出标准化字符串,而不是file解析有点脆弱的输出。file -i

答案2

由于不匹配的单引号,您的第一个file示例将不起作用,但我认为您已经因为第二个示例而发现了这一点。

如果你这样做:

find . -type f

你可以看看输出。这些是文件名。如果您想从该输出中选择某些内容,请grep直接使用

find . -type f  |  grep "Microsoft Word"

通过文件名进行搜索,而不是通过列出的文件的内容进行搜索。这并不完全准确,因为文件名中可能包含换行符,如果包含“Microsoft Word”的文件名包含换行符作为名称的一部分,则输出不完整。

如果你这样做:

find . -type f -print0 | xargs -0 grep -lh "Microsoft Word" 

xargs部分实际上将文件名传递给 grep (-print0forfind-0forxargs是处理带有换行符的文件名)。这会搜索整个字符串“Microsoft Word”而不仅仅是“Word”在文件中

指定的-lhforgrep列出文件名,并且可能存在问题,因为文件名中的换行符会正常打印,因此您还应该通过指定 -Z 继续使用 NUL 终止的文件名。如果您不指定,-l您也会得到行匹配的内容,这将使进一步处理(您的mv)变得不可能。

如果您想将所有文件移到一个目录中,通常更容易使用, mv -t而不是使用xargs'-I选项(它允许您xargs将从其输入读取的参数放在与默认行尾不同的位置,但速度较慢)因为每个文件都会调用一次 mv ):

find . -type f -print0 | xargs -0 grep -lhZ "Microsoft Word" | xargs -0 mv -t ../NewDirectory/

这会将所有文件移动到当前目录下的某个位置,其中包含“Microsoft Word”内容NewDirectory当前目录旁边的 。请注意,它../NewDirectory必须存在。

相关内容