打印所有目录和子目录功能

打印所有目录和子目录功能

我正在尝试使用下面的函数打印所有子目录,但由于某种原因,当文件名包含空格(“”)时,会将echo名称分为两部分。这是一个例子:

我的目录包含一个名为r1 August.request.

输出是:

r1

August.request

我正在寻找

r1     August.request

这是我的脚本:

#!/bin/bash

function ScanFile {
    for file in `ls` ; do  
    if [[ -d "$file" ]] ; then
            cd "$file"
            ScanFile
            cd ..
            else
            echo "$file"
    fi
    done
} 
ScanFile

答案1

SH 兼容 shell 中有所谓的 IFS 变量。 IFS 代表内部字段分隔符。此变量控制 shell 如何检测参数边界(如位置参数中的参数边界)。

默认情况下是:

set IFS=$' \t\n'

这意味着:将输入拆分为由空格、制表符和换行符分隔的标记。

您的文件由空格组成。尝试这样做:

OLD_IF="$IFS"
IFS=$'\t\n'
for file in `ls -1` ; do
     # Content of your loop
done
IFS="$OLD_IFS"

这里的要点是存储以前的 IFS 值并恢复它。

编辑:添加ls -1为每行列出一个文件,因此执行您提到的内容。

答案2

在bash中:

shopt -s globstar
ls -1d **/

答案3

您的函数解析 的未加引号的输出ls。这意味着 shell 将在ls.

反而:

dirwalk () {
    indent=${1:-0}

    for name in *; do
        [ ! -e "$name" ] && continue
        if [ -d "$name" ]; then
            printf '%*sDir: "%s"\n' "$indent" "" "$name"
            ( cd "$name" && dirwalk "$(( indent + 4 ))" )
        else
            printf '%*sFile: "%s"\n' "$indent" "" "$name"
        fi
    done
}

或者,没有花哨的缩进,

dirwalk () {
    for name in *; do
        [ ! -e "$name" ] && continue
        if [ -d "$name" ]; then
            printf 'Dir: "%s"\n' "$name"
            ( cd "$name" && dirwalk )
        else
            printf 'File: "%s"\n' "$name"
        fi
    done
}

通过使用*而不是 的输出ls,我们生成了一个正确分隔的文件名列表,以便在当前目录中进行迭代,即使这些文件名包含空格。

测试-e是为了确保我们迭代的东西确实存在。如果我们输入一个空目录,则*不会扩展并保留为*.在 中bash,您可以设置nullglobshell 选项(使用shopt -s nullglob)来使不匹配的模式扩展为空。

通过在子 shell 中(在括号内)使用cd,我们不必记住cd ..返回到上一个目录。外面的环境( ... )不会受到cd里面的影响。

使用printf而不是echo我们可以更好地控制输出的格式。另请参见“为什么 printf 比 echo 更好?”。

相关内容