管道模式输入查找命令

管道模式输入查找命令

我有一个场景,我尝试find根据另一个命令的输出来处理多个文件。

命令本身是

./libopt -d test . 2>&1 | sed -rn 's/Cannot find library \"(.*?)\"/\1/p'

这给了我以下输出

libopcodes-2.25-system.so
libbfd-2.25-system.so
libz.so.1
libdl.so.2
libc.so.6
libosal.so
libarchive.so.13
libcrypto.so.1.0.0
libfreetype.so.6
libpng12.so.0
libpthread.so.0
libts-1.0.so.0
libgcc_s.so.1
libssl.so.1.0.0
libm.so.6
ld-linux.so.3
libxml2.so.2
libbz2.so.1.0
liblzma.so.5
liblzo2.so.2
libattr.so.1
libacl.so.1
libnettle.so.4

无论如何,我可以将此输入提供给以下 find 命令,以便找到每个文件的位置吗?

find /usr -name <INPUT_LINE>

答案1

假设IFS库名称中不存在有问题的字符(例如 中的字符),循环遍历列表并将每个字符传递给新的查找:

./libopt -d test . 2>&1 | sed -rn 's/Cannot find library \"(.*?)\"/\1/p' \
| while read libname; do
  find /usr -name "$libname"
done

否则,对于单个文件系统传递(上面为每个输入文件执行一个),该find -name选项不适合匹配文件名列表,因此也许单个文件系统搜索的输出可以传递到grep.还可以通过仅查找/usr名为以下的目录来缩小搜索范围lib

./libopt -d test . 2>&1 | sed -rn 's/Cannot find library \"(.*?)\"/\1/p' > blah
find /usr/lib /usr/*/lib -type f | grep -F -f blah

mktemp如果blah有问题,请使用生成的文件名。使用精美的 shell,grep可以通过某种形式的进程替换动态生成模式文件。

答案2

您可以将文件名转换为单个正则表达式并使用或(不区分大小写)选项find-regex-iregex

libs=$(./libopt -d test . 2>&1 | 
       sed -rn 's/Cannot find library \"(.*?)\"/\1/p' | 
       xargs -r | sed -e 's/ /|/g ; s/\./\\./g')

[ -n "$libs" ] && find /usr -regextype egrep -iregex ".*/($libs)"

xargs将所有文件名放在一行上,并用空格分隔,以下命令sed将空格更改为|和。仅当 $libs 非空时才运行该命令。.\.find

注意:如果 输出太多(数千)个文件名./libopt,该xargs命令将输出 2 行或更多行,$libs 将太大而无法容纳在一个命令行中,这将中断。如果这是可能的(在我看来不太可能,考虑到输出的内容),您可以通过在循环中./libopt运行xargs | sedand来解决它,例如:find

libs=$(./libopt -d test . 2>&1 | sed -rn 's/Cannot find library \"(.*?)\"/\1/p')

for re in $(echo "$libs" | xargs | sed -e 's/ /|/g ; s/\./\\./g') ; do 
    find . -regextype egrep -iregex ".*/($re)"
done

答案3

zsh

files=(
  ${(f)"$(./libopt -d test . 2>&1 |
          sed -rn 's/Cannot find library \"(.*?)\"/\1/p')"})
glob=('$files['{1..$#files}']')
eval "paths=(**/(${(j:|:)glob})(D.))"
ls -ld -- $paths

请参阅类似问题的答案:https://unix.stackexchange.com/a/265815以获得解释以及一些替代方法(如果您没有)zsh

相关内容