在Linux中使用Bash列出带有空格的目录

3
我希望创建一个bash脚本,用于列出用户提供的目录中的所有目录(通过输入)或当前目录中的所有目录(如果没有输入)。以下是我到目前为止的代码,但当我执行时遇到了两个问题。1)脚本完全忽略了我的输入。文件位于我的桌面上,但当我键入“home”作为输入时,脚本仅打印Desktop(当前目录)的目录。2)目录单独显示在各自的行上(有意),但它将文件夹名称中的每个单词都视为其自己的目录。例如,被打印为:
this
folder

这是我目前的代码:

#!/bin/bash

echo -n "Enter a directory to load files: "
read d

if [ $d="" ]; #if input is blank, assume d = current directory
then d=${PWD##*/} 
for i in $(ls -d */);
do echo ${i%%/};
done
else #otherwise, print sub-directories of given directory
for i in $(ls -d */);
do echo ${i%%/};
done
fi

在您的回答中请解释您的答案,因为我对bash非常陌生。
谢谢您的查阅,感谢您的时间。
编辑: 感谢John1024的回答,我想到了以下内容:
#!/bin/bash

echo -n "Enter a directory to load files: "
IFS= read d
ls -1 -d "${d:-.}"/*/

它能满足我所有的需求,非常感激!

1个回答

3
我相信这个脚本可以实现你想要的功能:
#!/bin/sh
ls -1 -d "${1:-.}"/*/

使用示例:

$ bash ./script.sh  /usr/X11R6
/usr/X11R6/bin
/usr/X11R6/man

解释:

  • -1 告诉 ls 将每个文件/目录分别打印到一行

  • -d 告诉 ls 按名称列出目录而不是其内容

  • 如果脚本有第一个参数,则 shell 会将 ${1:-.} 设为第一个参数,否则为 .(表示当前目录)。

增强版

上面的脚本在每个目录名后面显示 /。如果不想要这样的输出,我们可以使用 sed 来删除尾随斜杠:

#!/bin/sh
ls -1d ${1:-.}/*/ | sed 's|/$||'

您的脚本的修订版本

从您的脚本开始,可以进行一些简化:

#!/bin/bash
echo -n "Enter a directory to load files: "
IFS= read d
d=${d:-$PWD}
for i in "$d"/*/
do
    echo ${i%%/}
done

注:

  • IFS= read d

    Normally leading and trailing white space are stripped before the input is assigned to d. By setting IFS to an empty value, however, leading and trailing white space will be preserved. Thus this will work even if the pathologically strange case where the user specifies a directory whose name begins or ends with white space.

    If the user enters a backslash, the shell will try to process it as an escape. If you don't like that, use IFS= read -r d and backslashes will be treated as normal characters, not escapes.

  • d=${d:-$PWD}

    If the user supplied a value for d, this leaves it unchanged. If he didn't, this assigns it to $PWD.

  • for i in "$d"/*/

    This will loop over every subdirectory of $d and will correctly handle subdirectory names with spaces, tabs, or any other odd character.

    By contrast, consider:

    for i in $(ls -d */)
    

    After ls executes here, the shell will split up the output into individual words. This is called "word splitting" and is why this form of the for loop should be avoided.

    Notice the double-quotes in for i in "$d"/*/. They are there to prevent word splitting on $d.


非常感谢您的回答!我使用了您的输入(预编辑)并编写了一个更短、更优雅的程序! - Robert Howerton
@RobertHowerton 非常好!我刚刚编辑了我的答案,并在您的编辑中添加了双引号和 IFS=,因为我之前不小心漏掉了它们。它们使得脚本即使用户提供的目录名称中有空格或制表符也能正常工作。 - John1024

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接