有一个 bash 命令文件(1),它根据 /etc/magic 和 /usr/share/misc/magic 中的匹配模式定义输出文件的内容类型。
有没有办法使用这些模式定义“魔术”文件作为“查找”命令的测试?
例如,有一些文本文件和“PalmOS应用程序”文件
file -b palmapp
PalmOS application
file -b readme.txt
ASCII text
我需要某种方法来查找与“PalmOS 应用程序”而不是“ASCII 文本”匹配的文件,例如这是一个理想的命令:
find . -magic "PalmOS*"
有没有想法为这个测试的每个文件编写一个单行 bash 命令?
答案1
大致如下:
find . -print -exec file {} \; | grep "PalmOS"
要通过 awk 整理输出管道,请添加:
| awk '{print substr($1,2,length($1)-2)}'
答案2
没有内置功能来find
分析文件内容,但您可以让它调用file
.使用 shell 组合多个特定于任务的程序(find
遍历目录树、file
分析文件内容)是 Unix 的处理方式。
您想要对命令输出file -b -- "$filename"
包含字符串的文件进行操作PalmOS application
。可以用shell脚本测试一下
case "$(file -b -- "$filename")" in *"PalmOS application"*) true;; *) false;; esac
find
您可以在如下命令中使用此脚本:
find . -type f -exec sh -c 'case "$(file -b "$0")" in *"PalmOS application"*) true;; *) false;; esac' {} \; -print
替换-print
为您要执行的操作(可以是另一个-exec …
)。仅当前一个操作为 true(即 shell 命令返回 0(即 true))时,才会执行第二个操作。
或者,在 zsh 中,您可以让 shell 使用以下命令进行目录遍历**
全局。这.
全局限定符将匹配限制为常规文件(例如-type f
for find
)。
for x in **/*(.); do
[[ $(file -b -- $x) = *"PalmOS application"* ]] || continue
…
done
在 bash ≥4.3 中,您可以使用**
递归通配符,但您需要globstar
先启用该选项。在 bash 4.0–4.2 中,globstar
已经可用,但要注意**
遍历目录的符号链接。在 ksh93 中,使用set -o globstar
代替shopt -s globstar
.
shopt -s globstar
for x in **/*; do
[[ -f $x ]] || continue
[[ $(file -b -- "$x") = *"PalmOS application"* ]] || continue
…
done
如果您的文件名不包含空格或任何空格,:\"'
则另一种方法是在文件名上运行file
并解析输出。
find -type f |
xargs file |
sed -n 's/:.*PalmOS application.*//p' |
xargs somecommand
如果您的文件名包含空格但没有换行符或冒号,那么您可以使用 shell 进行解析。
find -type f |
while IFS=: read -r filename type; do
case "$type" in
*"PalmOS application"*)
…;;
esac
done
答案3
这不使用find
,而是设置pattern
并将directory
产生您的问题所要求的结果:
pattern="PalmOS application"
directory=.
for f in $directory/*; do
if [[ $(file -b $f) == "$pattern" ]]; then
echo $f;
fi;
done