简体   繁体   English

递归区分bash中的文件和目录

[英]Recursively differentiating files and directories in bash

Bash here. 在这里重击。 Looking to write a script that: 寻找编写一个脚本,该脚本:

  • Takes a absolute/relative target directory as its sole input argument and loops through its contents 将绝对/相对目标目录作为唯一的输入参数并遍历其内容
  • If one of its direct children is a file, I want it to echo " Found a file called $file! " (where $file is the name of the file) 如果它的直接子级之一是文件,我希望它回显“ Found a file called $file! ”(其中$file是文件名)
  • Else, if one of its direct children is itself a directory, I want it to echo " Found a directory named $dir " (where $dir is the name of the directory), but then I want it to recursively execute with this same exact logic inside that directory, and finally I want it to continue looping through the rest of the target directory 否则,如果它的直接子级之一本身就是目录,我希望它回显“ Found a directory named $dir ”(其中$dir$dir的名称), 但是然后我希望它以相同的方式递归执行该目录中的逻辑,最后我希望它继续遍历目标目录的其余部分

Hence given the following target directory structure: 因此,给出以下目标目录结构:

~/testDir/
    1.txt
    2.txt
    childDirA/
        foo.png
    3.txt
    childDirB/
        buzz.gif
        childDirC/
            foo.bar
    4.txt

The output of the script would be: 该脚本的输出为:

Found a file called 1.txt!
Found a file called 2.txt!
Found a directory named childDirA
Found a file called foo.png!
Found a file called 3.txt!
Found a directory named childDirB
Found a file called buzz.gif!
Found a directory named childDirC
Found a file called foo.bar!
Found a file called 4.txt!

So far the best I've been able to come up with is: 到目前为止,我能想到的最好的方法是:

#!/bin/bash
for file in $1;
  do echo "Found a file called $file";
done

However if I point this at my testDir the only output I get is: 但是,如果我将此指向我的testDir则得到的唯一输出是:

Found a file called testDir

Any ideas where I'm going awry? 有什么想法我要去哪里吗?

Here's a script that'll do that. 这是将执行此操作的脚本。

function listDir() {
    for file in "$1"/*;
    do
        if [ -f "$file" ]; then
            echo "Found file $(basename "$file")"
        elif [ -d "$file" ]; then
            echo "Found directory $(basename "$file")"
            listDir "$file"
        fi
    done
}

listDir "$1"

As Tripp mentioned in the comments, find can do the 'recursive' work for you; 正如Tripp在评论中所述, find可以为您完成“递归”工作; then you just need to tweak the output into the format you want. 那么您只需要将输出调整为所需的格式即可。

Assuming you only need to worry about files and directories: 假设您只需要担心文件和目录:

#!/usr/bin/bash

while IFS= read -d "" -r tgt
do
        # for printing purposes, strip off directory info; basically simulate
        # `basename` without the overhead of spawning an expensive sub-process

        tgtname=${tgt##*/}

        # determine tgt's type : 'file' or 'directory'

        tgttype='file'
        [ -d "${tgt}" ] && tgttype='directory'

        echo "Found a ${tgttype} named ${tgtname}"

done < <(find "$1" -print0)

NOTES: 笔记:

  • run find $1 by itself to see the format of the data being fed into the loop 单独运行find $1以查看送入循环的数据的格式
  • add additional tests to determine tgttype if you're dealing with links, devices, etc (perhaps use a case statement?) 如果要处理链接,设备等,则添加其他测试以确定tgttype (也许使用case语句?)
  • consider additional command line args/params to find to fine tune the list that's fed into the loop 考虑附加的命令行参数/ PARAMS来find微调是美联储进入循环列表

Find

#!/bin/sh
find "$1" -mindepth 1 -type f -printf 'Found a file called %f!\n' -o -type d -printf 'Found a directory named %f\n'

Explanation: 说明:

By default, find recurses through subdirectories. 默认情况下,通过子目录find递归。

Arguments to find : find参数:

  • -mindepth 1 Exclude the base directory -mindepth 1排除基本目录
  • -type f ... If a normal file is found, do the following -type f ...如果找到普通文件,请执行以下操作
  • -o -type d ... Or, if a directory is found, do the following -o -type d ...或者,如果找到目录,请执行以下操作
  • -printf ... Print according to the given format string -printf ...根据给定的格式字符串打印
  • %f The basename of the file (dirs are files in this context) %f文件的基本名称(目录是此上下文中的文件)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM