2

因此,经过大量搜索并试图解释其他人的问题和对我需求的回答后,我决定问自己。

我正在尝试采用一个充满图像的目录结构并将所有图像(无论扩展名如何)放在一个文件夹中。除此之外,我希望能够在此过程中删除与某些文件名匹配的图像。我有一个 find 命令可以为我输出所有文件路径

find -type f -exec file -i -- {} + | grep -i image | sed 's/\:.*//'

但是如果我尝试使用它来复制文件,我会遇到文件名中的空格问题。

cp `find -type f -exec file -i -- {} + | grep -i image | sed 's/\:.*//'` out/

我做错了什么,有没有更好的方法来做到这一点?

4

3 回答 3

2

需要注意的是,如果文件的名称中有换行符,它将不起作用:

find . -type f -exec file -i -- {} + |
awk -vFS=: -vOFS=: '$NF ~ /image/{NF--;printf "%s\0", $0}' |
xargs -0 cp -t out/

(基于 Jonathan Leffler 的回答以及随后与他和@devnull 的评论讨论。)

于 2013-09-07T06:29:56.063 回答
1

find如果没有文件名包含任何换行符,该命令运行良好。在广泛的范围内,该grep命令在相同情况下工作正常。sed只要文件名中没有冒号,该命令就可以正常工作。但是,鉴于名称中有空格,使用$(...)(命令替换,也由反引号表示`...`) 是一场灾难。不幸的是,xargs这不是解决方案的一部分;默认情况下,它会在空格上拆分。因为你必须运行file并且grep在中间,你不能轻易地使用-print0选项 to (GNU)find-0选项 to (GNU) xargs

在某些方面,它很粗糙,但在许多方面,如果您编写一个可执行的 shell 脚本,它可以被调用find

#!/bin/bash

for file in "$@"
do
    if file -i -- "$file" | grep -i -q "$file:.*image"
    then cp "$file" out/
    fi
done

这有点痛苦,因为它为每个名称单独调用file和调用,但它是可靠的。如果文件名包含换行符,grep该命令甚至是安全的;可能不是filegrep

如果该脚本称为“copyimage.sh”,则find命令变为:

find . -type f -exec ./copyimage.sh {} +

而且,鉴于grep命令的编写方式,copyimage.sh文件不会被复制,即使它的名称包含神奇的单词“图像”。

于 2013-09-07T06:04:06.187 回答
0

将 find 命令的结果通过管道传输到

xargs -l --replace cp "{}" out/

在 Ubuntu 10.04 上如何为我工作的示例:

atomic@atomic-desktop:~/temp$ ls
img.png  img space.png
atomic@atomic-desktop:~/temp$ mkdir out
atomic@atomic-desktop:~/temp$ find -type f -exec file -i \{\} \; | grep -i image | sed 's/\:.*//' | xargs -l --replace cp -v "{}" out/
`./img.png' -> `out/img.png'
`./img space.png' -> `out/img space.png'
atomic@atomic-desktop:~/temp$ ls out
img.png  img space.png
atomic@atomic-desktop:~/temp$ 
于 2013-09-07T06:06:50.217 回答