如何在Linux Bash中将ls分配给数组?

Jor*_*sef 64 arrays bash shell ls

array=${ls -d */}
echo ${array[@]}  
Run Code Online (Sandbox Code Playgroud)

我有三个目录:ww ee qq.我希望它们在一个数组中然后打印数组.

Aar*_*ano 85

就是这样

array=($(ls -d */))
Run Code Online (Sandbox Code Playgroud)

编辑:请参阅Gordon Davisson的解决方案以获得更一般的答案(即,如果您的文件名包含特殊字符).这个答案仅仅是语法修正.

  • 如果目录名称包含空格,则无法正常工作. (12认同)
  • 我的错。那应该是双引号,以便可以扩展命令替换。`ARR+=("$(ls -d */)")` 应该可以工作。如果没有,请告诉我。 (2认同)
  • @Yokai,这总共只添加了 *one* 个元素(其中包含一堆换行符),而不是每个目录一个元素。 (2认同)
  • 根据 shellcheck,以下内容将是更好的选择: `mapfile -t content < <(ls -d -- *)` 原始解决方案存在两个问题:(i) 不支持路径中的空格,以及 (ii)以破折号开头的文件名被解释为“ls”的参数,而不是文件名。 (2认同)

Gor*_*son 59

只要有可能,你应该避免解析输出ls(参见Greg关于这个主题的维基).基本上,ls如果任何文件名中都有滑稽的字符,输出将是不明确的.这通常也是浪费时间.在这种情况下,当你执行时ls -d */,会发生的事情是shell扩展*/到一个子目录列表(这已经是你想要的了),将该列表作为参数传递给ls -d每一个,查看每个子目录,"是的,这是一个目录好吧"并打印出来.该ls命令没有做任何有用的事情!

嗯,好吧,它正在做一件有用的事情:如果没有子目录,*/将保持原样,ls将查找名为"*"的子目录,找不到它,打印一条不存在的错误消息(至stderr),而不是打印"*/"(到stdout).

创建子目录名称数组的更简洁方法是使用glob(*/)而不传递它ls.但是为了避免在没有实际子目录的情况下在数组中放入"*/",你应该先设置nullglob(再次参见Greg的wiki):

shopt -s nullglob
array=(*/)
shopt -u nullglob # Turn off nullglob to make sure it doesn't interfere with anything later
echo "${array[@]}"  # Note double-quotes to avoid extra parsing of funny characters in filenames
Run Code Online (Sandbox Code Playgroud)

如果您想在没有子目录时打印错误消息,最好自己动手:

if (( ${#array[@]} == 0 )); then
    echo "No subdirectories found" >&2
fi
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的评论,即使没有标记为答案,它提供了相当丰富的信息,我很感激. (2认同)

kon*_*box 6

这将逐行打印这些目录中的文件.

array=(ww/* ee/* qq/*)
printf "%s\n" "${array[@]}"
Run Code Online (Sandbox Code Playgroud)