要扁平化目录结构,我可以这样做:
find . -type f -exec sh -c 'mv "{}" "./`basename "{}"`"' \;
Run Code Online (Sandbox Code Playgroud)
我想将以下内容作为 $FLATTEN 存储在我的个人资料中
-exec sh -c 'mv "{}" "./`basename "{}"`"' \;
Run Code Online (Sandbox Code Playgroud)
这样以后我就可以执行 find . $FLATTEN
我在存储变量时遇到问题,因为它过早地被解释。我希望将它存储为字符串文字,并且仅在 shell 上使用时进行解释,而不是在来源时进行解释。
如果使用 GNU mv,您应该这样做:
find . -type f -exec mv -t . {} +
Run Code Online (Sandbox Code Playgroud)
与其他mvs:
find . -type f -exec sh -c 'exec mv "$@" .' sh {} +
Run Code Online (Sandbox Code Playgroud)
你永远不应该嵌入{}的sh代码。这是一个命令注入漏洞,因为文件的名称被解释为 shell 代码(例如尝试使用一个名为的文件`reboot`)。
对于引用命令替换好一点,但由于您使用的是古老的形式(`...`而不是$(...)),你需要躲避内双引号或将在不工作sh的实现基于Bourne shell或AT&T的ksh(其中"`basename "foo bar"`"会实际上被视为"`basename "(具有`在这些 shell 中被接受的不匹配)与foo和 then连接bar"`")。
此外,当您执行以下操作时:
mv foo/bar bar
Run Code Online (Sandbox Code Playgroud)
如果bar确实存在并且是一个目录,那实际上是一个mv foo/bar bar/bar. mv -t . foo/bar或者mv foo/bar .没有那个问题。
现在,要将这几个参数 ( -exec, sh, -c, exec mv "$@" ., sh, {}, +) 存储到变量中,您需要一个数组变量。支持数组的外壳是(t)csh, ksh, bash, zsh, rc, es, yash, fish。
并且为了能够直接使用该变量$FLATTEN(而不是"${FLATTEN[@]}"在 ksh/bash/yash 或$FLATTEN:qin 中(t)csh),您需要一个具有合理数组实现的外壳:rc,es或fish. 还zsh在这里,这些参数都不是空的。
在rc/ es/ zsh:
FLATTEN=(-exec sh -c 'exec mv "$@" .' sh '{}' +)
Run Code Online (Sandbox Code Playgroud)
在fish:
set FLATTEN -exec sh -c 'exec mv "$@" .' sh '{}' +
Run Code Online (Sandbox Code Playgroud)
然后你可以使用:
find . -type f $FLATTEN
Run Code Online (Sandbox Code Playgroud)