如何在bash中获取目录列表,然后将它们作为命令行参数展开?

时间:2011-06-24 02:56:44

标签: bash command-line-arguments

我正在编写一个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'调用一次脚本。

有没有直接的方法来做这种事情?我一直在谷歌搜索,我已经设法找出最好的,要求我知道有多少目录。

4 个答案:

答案 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

在第二个示例中,请注意谨慎使用\0xargs -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,并确保即使目录名中有空格也能正确传递它们。