我正在编写一个bash脚本,它需要一步获取目标目录(可能还包含文件)中的目录列表(变量),然后将它们作为参数展开到python脚本中。
示例:
/stuff/a dir/
/stuff/b other/
/stuff/c/
我需要在bash脚本中调用:
script.py "a dir/" "b other/" "c/"
或者,转义空格:
script.py a\ dir/ b\ other/ c/
我需要为目录'stuff'调用一次脚本。
有没有直接的方法来做这种事情?我一直在谷歌搜索,我已经设法找出最好的,要求我知道有多少目录。
答案 0 :(得分:15)
这是一项寻找工作。
find /stuff -type d -exec script.py {} +
当您使用-exec
时,花括号{}
将替换为匹配文件的名称,+
表示命令的结束(如果您想告诉查找到采取其他行动)。这是使用find执行命令的理想方法,因为它将正确处理具有异常字符(如空格)的文件名。
find非常灵活,特别是如果您的GNU版本通常与Linux发行版捆绑在一起。
# Don't recurse into subdirectories.
find /stuff -maxdepth 1 -type d -exec script.py {} +
# Pass in a/, b/, c/ instead of /stuff/a/, /stuff/b/, /stuff/c/.
find /stuff -type d -printf '%P\0' | xargs -0 script.py
在第二个示例中,请注意谨慎使用\0
和xargs -0
来使用NUL字符来分隔文件名。它可能看起来很奇怪,但即使你做了一些非常奇怪的事情,比如在目录名中使用换行符\n
,这也可以让命令工作。
或者,您可以仅使用shell内置函数来执行此操作。我不推荐这个,但为了教育价值,这里是如何:
# Start with an empty array.
DIRS=()
# For each file in /stuff/...
for FILE in /stuff/*; do
# If the file is a directory add it to the array. ("&&" is shorthand for
# if/then.)
[[ -d $FILE ]] && DIRS+=("$FILE")
# (Normally variable expansions should have double quotes to preserve
# whitespace; thanks to bash magic we don't them inside double brackets.
# [[ ]] has special parsing rules.)
done
# Pass directories to script. The `"${array[@]}"` syntax is an unfortunately
# verbose way of expanding an array into separate strings. The double quotes
# and the `[@]` ensure that whitespace is preserved correctly.
script.py "${DIRS[@]}"
答案 1 :(得分:4)
一个不创建新流程的简单解决方案(如查找一样)是:
for f in stuff/*; do
if [ -d "$f" ]; then
./script.py "$f"
fi
done
答案 2 :(得分:2)
您可以使用查找命令,并告诉它只打印出 -type d 的目录。您的命令将如下所示:
script.py $(find /stuff/* -type d)
如果您担心空格和其他特殊字符,可以这样做:
script.py $(find /stuff/* -type d | while read line; do echo "\"$line"\"; done)
答案 3 :(得分:1)
find /stuff/* -type d -maxdepth 1 -print0 | xargs -0 script.py
这将找到/ stuff下的所有目录,但不会递归并将它们传递给script.py,并确保即使目录名中有空格也能正确传递它们。