Mar*_*tus 18 shell directory find directory-structure files
当我运行时find,-execdir我没有得到我期望的结果。
例如:
mkdir -p a/b/c
find . -type d -execdir touch foo \;
$ tree a
a
??? b
? ??? c
? ??? foo
??? foo
Run Code Online (Sandbox Code Playgroud)
目录c不包含foo文件。如何find在每个目录中访问并在本地执行某些操作?
Gil*_*il' 19
对于每个匹配的文件(即每个目录),find切换到包含它的目录(即其父目录)并执行指定的命令。由于该命令不使用匹配项的名称,因此它永远不会作用于所有目录。对于这个特定的目录树,你正在做
(cd . && touch foo) # because ./a matches
(cd ./a && touch foo) # because ./a/b matches
(cd ./a/b && touch foo) # because ./a/b/c matches
Run Code Online (Sandbox Code Playgroud)
要在每个目录中创建一个文件,您可以简单地使用-exec代替-execdir,前提是您在参数中实现了find允许{}(大多数都这样做,特别是我认为所有的):
find . -type d -exec touch {}/foo +
Run Code Online (Sandbox Code Playgroud)
对于 POSIX 可移植性,您需要手动组装目录名和文件基名。
find . -type d -exec sh -c 'touch "$0/foo"' {} \;
Run Code Online (Sandbox Code Playgroud)
或(稍快)
find . -type d -exec sh -c 'for d; do touch "$d/foo"; done' _ {} +
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用 bash 的递归通配符匹配。请注意(与 ksh 和 zsh 中的相应功能不同,并且与您的find命令不同)bash 在指向目录的符号链接下递归。
shopt -s globstar
for d in **/*/; do touch -- "$d/foo"; done
Run Code Online (Sandbox Code Playgroud)
zsh 解决方案:
touch ./**/(e\''REPLY+=foo'\')
Run Code Online (Sandbox Code Playgroud)
该命令在包含匹配文件的每个目录中执行。由于c不包含目录,因此它不匹配,因此不会在那里运行。
解决方案是将目录名称添加到 execdir 参数中,如下所示:
find . -type d -execdir touch {}/foo \;
Run Code Online (Sandbox Code Playgroud)