我必须递归搜索所有子目录并打印*(*的数量=文件/目录的深度)类型和名称。 问题出在我输入目录然后想离开但什么也没发生的时候。

我的测试文件

DIR test
*FILE ace
*FILE base
*DIR father
**FILE cookies
*DIR mother
**DIR how
***FILE youdoing
*FILE zebra

我的代码

maxDepth是它可以进入目录的距离(默认为3),而currDepth在开始时为1

    function tree(){
        maxDepth=$2
        currDepth=$3
        #print the starting file
        if [ "$currDepth" -eq 0 ];then
            printf  "%s   %s\n" DIR "$1"
            currDepth=1
        fi
        for path in "$1"/*;do
            for i in $( seq 1 $currDepth );do       
                echo -n *
            done
            if [ -d "$path" ];then
                printf  "%s   %s\n" DIR "${path##*/}"           
                if [[ "$currDepth" -lt "$maxDepth" ]];then
                    tree "$path" "$maxDepth" "$(( currDepth + 1 ))"
                fi
                continue
            fi
            if [ -f "$path" ];then      
                printf "%s  %s\n" FILE "${path##*/}"
                continue
            fi
            if [ -L "$path" ];then
                printf "%s  %s\n" LINK "${path##*/}"
                continue            
            fi
       done
  }

我的输出

DIR test
*FILE ace
*FILE base
*DIR father
**FILE cookies
**DIR mother
***DIR how
***FILE zebra

我究竟做错了什么

===============>>#1 票数:1

  1. 在运行脚本之前,先执行set -x调试脚本。
  2. 通过使用-i integer属性声明整数,确保整数始终是整数。
  3. 始终使用表达式语法。 如果目标shell是bash,则始终使用[[ ]]测试进行字符串比较,并使用(( ))进行算术和数字比较是一个好主意。
  4. 使用(( ))代替非标准seq进行循环。
  5. 在函数中明确声明您的变量(使用localdeclare ),以确保它们的作用域属于该函数。
  6. 居然叫内tree

#!/bin/bash
tree() {
    local -i maxDepth=$2 # Make sure these values are always integers
    local -i currDepth=$3

    # print the starting file
    if (( currDepth == 0 )); then # use bash arithmetic
        printf  "%s   %s\n" DIR "$1"
        currDepth=1
    fi
    for path in "$1"/*;do
        for ((i=0; i<currDepth; i++)); do
            printf '*'
        done
        if [[ -d "$path" ]];then
            printf  "%s   %s\n" DIR "${path##*/}"           
            if [[ "$currDepth" -lt "$maxDepth" ]];then
                tree "$path" "$maxDepth" "$(( currDepth + 1 ))"
            fi
            continue
        fi
        if [[ -f "$path" ]];then      
            printf "%s  %s\n" FILE "${path##*/}"
            continue
        fi
        if [[ -L "$path" ]];then
            printf "%s  %s\n" LINK "${path##*/}"
            continue            
        fi
   done
}

===============>>#2 票数:1

这里是使用find,stat和sed的解决方案:

find <DIR> -exec stat --printf="%n,%F\n" "{}" \; | \
 sed -r -e "s/[^\/]+\//\*/g" -e "s/regular file/FILE/" -e "s/directory/DIR/" | \
 sed -r -e "s/([\*]+)([^,]+),(.+)/\1 \3 \2/"

重要说明:使用DIR而不是DIR /否则DIR名称将不会出现在结果中。

说明:

find递归返回DIR中的所有文件和目录。

find -exec选项允许将每个结果传递给另一个命令。 在这里,我将每个结果传递给命令stat

stat有一个格式化输出-printf的选项(请参见手册页):

  • %n是文件名(具有相对路径)
  • %F是文件类型(常规文件,目录,符号链接,阻止特殊文件...)

所以,

find <DIR> -exec stat --printf="%n,%F\\n" "{}" \\;

返回以下一行结果(假设DIR中仅包含常规文件和目录):

DIR/path/to/file,regular file
DIR/path/to/dir,directory

然后,我使用sed使用正则表达式按照您需要的方式变换每一行:

  1. string/替换为* -> ***basename,file type
  2. FILE替换"regular file"
  3. DIR替换"directory"
  4. 在sed中使用向后引用在基basenamefiletype周围随机播放。

注意:我不会详细解释正则表达式的工作方式,因为它可能太长。

===============>>#3 票数:0 已采纳

我应该在currDepth=$3之前使用local

  ask by TheGuyWithStreetCred translate from so

未解决问题?本站智能推荐:

关注微信公众号