如何通过 shell 脚本创建显示所有目录的命令?

How to create a command that shows all directories, through a shell script?

我想创建一个命令来显示作为参数给定的目录中的所有目录。例如,如果我们的文件层次结构是这样的:

dir1:
    dir2
    dir3
    file1
    dir4:
        file2
        dir5

那么rep dir1的结果应该是:

dir2
dir3
dir4

rep dir1/dir4 应该显示:

dir5

目前我有一个 shell 脚本 rep.sh 执行以下操作:

function rep(){
    all=`ls `
    for each in $all
    do 
        if [ -d $each ]
        then
            echo $each
        fi
    done
}

通过 bash rep.sh 执行此脚本不会执行任何操作,我认为这是正确的,但是当我执行 rep dir1rep dir1/dir4 时它不会显示任何内容。我认为我的错误在于我没有正确使用函数环境,或者我没有正确传递参数。

您可以使用 find and basename

...
find "" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;
...

选项-mindepth 1-maxdepth 1 阻止列出基目录或下降到子目录。 -type d 应用过滤器以便仅列出目录,并且 -exec basename {} \; 对找到的项目执行 basenamebasename 剥离路径,以便仅打印目录名称本身。

纯Bash:

rep() {
    for dir in ""/*/; do
        dir=${dir%/}
        printf '%s\n' "${dir##*/}"
    done
}

glob ""/*/ 获取所有目录;两个参数扩展然后删除尾部斜杠和目录路径。

这会忽略隐藏目录;如果您也想要这些,则必须打开 dotglob shell 选项。要保留 shell 选项的设置,您可以像这样包装函数:

rep() {
    local dg
    # Get current dotglob setting
    dg=$(shopt -p dotglob)
    # Enable dotglob
    shopt -s dotglob
    for dir in ""/*/; do
        dir=${dir%/}
        printf '%s\n' "${dir##*/}"
    done
    # Set dotglob back to what it was
    $dg
}

至于为什么你的脚本不起作用:在你分配给它之后看看 all 中包含的内容。

$ all=$(ls "")
$ declare -p all
declare -- all="dir2
dir3
dir4
file1"

(请注意,我还用 $() 和双引号 </code> 替换了过时的反引号。)</p> <p><code>ls 的输出不包含目录的路径,这就是为什么你的 -d 测试 returns 一切都是假的。

您使用 ls 的方式很容易出错:分词和参数扩展会使这样的脚本对于任何带有空白或 shell 元字符的文件名都失败(请参阅 Why you shouldn't parse the output of ls(1)).请改用 glob。

三个错误:

1)

的用法
all=`ls `

而不是

all=""/*

@Benjamin W. 指出。

2) 我忘记将 rep 放在 rep.sh 文件的末尾。该文件因此看起来像:

function rep(){
    all=""/*    
    for each in $all
    do 
        if [ -d $each ]
        then
            echo $each
        fi
    done
}

rep 

3) 在命令行中,我需要输入alias rep="bash rep.sh"才能在命令行中自由使用命令rep