Bash查找过滤器和副本 - 空格问题

时间:2013-09-07 05:15:16

标签: bash find

所以经过大量的搜索并试图解释别人的问题并解答我的需求后,我决定自问。

我正在尝试使用一个充满图像的目录结构,并将所有图像(无论扩展名)放在一个文件夹中。除此之外,我希望能够删除与过程中的某些文件名匹配的图像。我有一个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/

我做错了什么,有更好的方法吗?

3 个答案:

答案 0 :(得分: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的评论讨论。)

答案 1 :(得分:1)

如果没有文件名包含任何换行符,则find命令可以正常工作。在宽范围内,grep命令在相同的情况下可以正常工作。只要文件名中没有冒号,sed命令就可以正常工作。但是,鉴于名称中有空格,使用$(...)(命令替换,也用反向标记`...`表示)是一种灾难。不幸的是,xargs并不是解决方案的一部分;它默认在空格上分割。因为您必须在中间运行filegrep,所以您无法轻松使用-print0选项(GNU)find-0选项到(GNU)xargs

在某些方面,它很粗糙,但在很多方面,如果你编写一个可由find调用的可执行shell脚本,这是最简单的:

#!/bin/bash

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

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

如果该脚本名为'copyimage.sh',则find命令变为:

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

并且,考虑到编写grep命令的方式,copyimage.sh文件将不会被复制,即使其名称包含魔术词'image'。

答案 2 :(得分: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$