24
find . -name "filename including space" -print0 | xargs -0 ls -aldF > log.txt
find . -name "filename including space" -print0 | xargs -0 rm -rdf

是否可以将这两个命令合并为一个,以便只完成 1 个查找而不是 2 个?

我知道 xargs -I 可能有办法做到这一点,这可能会在处理包含空格的文件名时导致错误。非常感谢任何指导。

4

8 回答 8

49
find . -name "filename including space" -print0 | 
  xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt; rm -rdf {}'

刚刚碰到这个,我们可以减少调用 shell 的频率:

find . -name "filename including space" -print0 | 
  xargs -0 sh -c '
      for file; do
          ls -aldF "$file" >> log.txt
          rm -rdf "$file"
      done
  ' sh

尾随的“sh”在 shell 中变为 $0。xargs将文件(从 中返回find)作为命令行参数提供给 shell:我们使用 for 循环遍历它们。

于 2011-09-19T15:51:05.727 回答
16

如果您只是想避免find多次执行,您可以在tee之后立即执行find,将find输出保存到文件中,然后执行以下行:

find . -name "filename including space" -print0 | tee my_teed_file | xargs -0 ls -aldF > log.txt
cat my_teed_file | xargs -0 rm -rdf 

完成同样事情的另一种方法(如果确实是您想要完成的)是将输出存储find在变量中(假设它不是 TB 数据):

founddata=`find . -name "filename including space" -print0`
echo "$founddata" | xargs -0 ls -aldF > log.txt
echo "$founddata" | xargs -0 rm -rdf
于 2011-09-19T15:03:01.083 回答
5

我相信现在所有这些答案都给出了解决这个问题的正确方法。我尝试了 Jonathan 的 2 种解决方案和 Glenn 的方式,所有这些都在我的 Mac OS X 上运行良好。 mouviciel 的方法在我的操作系统上不起作用可能是由于某些配置原因。而且我认为它类似于乔纳森的第二种方法(我可能错了)。

正如对 Glenn 方法的评论中提到的,需要进行一些调整。所以这是我尝试过的命令,它非常适合仅供参考:

find . -name "filename including space" -print0 | 
xargs -0 -I '{}' sh -c 'ls -aldF {} | tee -a log.txt ; rm -rdf {}'

或者按照 Glenn 的建议更好:

find . -name "filename including space" -print0 | 
xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt ; rm -rdf {}'
于 2011-09-20T00:00:17.927 回答
4

只要文件名中没有换行符,GNU Parallel 就不需要 -print0:

find . -name "My brother's 12\" records" | parallel ls {}\; rm -rdf {} >log.txt

观看介绍视频以了解更多信息:http ://www.youtube.com/watch?v=OpaiGYxkSuQ

于 2011-09-20T17:06:37.867 回答
2

只是xargs方法的一种变体,没有那种可怕的-print0and xargs -0,这就是我的做法:

ls -1 *.txt  | xargs --delimiter "\n" --max-args 1 --replace={} sh -c 'cat {}; echo "\n"'

脚注:

  • 是的,我知道换行符可以出现在文件名中,但是在他们正确的头脑中谁会这样做
  • 有一些简短的选项,xargs但为了读者的理解,我使用了较长的选项。
  • ls -1当我想要非递归行为而不是find -maxdepth 1 -iname "*.txt"更冗长时,我会使用它。
于 2015-10-14T18:14:25.147 回答
1

find您可以在使用之后执行多个命令for而不是xargs

IFS=$'\n'
for F in `find . -name "filename including space"`
do
    ls -aldF $F > log.txt
    rm -rdf $F
done

定义内部IFS字段分隔符,默认为 <space><tab><newline>。如果您的文件名可能包含空格,则最好像上面那样重新定义它。

于 2014-07-15T10:16:19.110 回答
1

我迟到了,但这里没有介绍另一种解决方案:用户定义的函数。将多条指令放在一行上很笨拙,并且很难阅读/维护。上面的 for 循环避免了这种情况,但有可能超过命令行长度。

这是另一种方式(未经测试)。

function processFiles {
  ls -aldF "$@"
  rm -rdf "$@"
}
export -f processFiles

find . -name "filename including space"` -print0 \
  | xargs -0 bash -c processFiles dummyArg > log.txt

这很简单,除了“dummyArg”让我很伤心。以这种方式运行 bash 时,参数被读入

"$0" "$1" "$2"  ....

而不是预期的

"$1" "$2" "$3"    ....

由于 processFiles{} 期望第一个参数是“ $1 ”,我们必须在“ $0”中插入一个虚拟值。

脚注:

  1. 我正在使用 bash 语法的一些元素(例如“ export -f ”),但我相信这会适应其他 shell。
  2. 我第一次尝试这个时,我没有添加一个虚拟参数。相反,我在函数内的参数行中添加了“ $0 ”(例如ls -aldf "$0" "$@")。馊主意。除了风格问题之外,当“ find ”命令什么也不返回时它会中断。在这种情况下,$0 设置为“bash”,而使用 dummy 参数可以避免所有这些。
于 2016-03-27T02:37:29.500 回答
0

另一种解决方案:

find . -name "filename including space" -print0 \
| xargs -0 -I FOUND echo "$(ls -aldF FOUND > log.txt ; rm -rdf FOUND)"
于 2011-09-19T15:50:41.267 回答