简体   繁体   English

Bash:如何控制迭代流/循环?

[英]Bash: How to control iteration flow/loops?

For going over some recovered data, I am working on a script that recursively goes through folders & files and finally runs file on them, to check if they are likely fully recovered from a certain backup or not. 为了查看一些恢复的数据,我正在编写一个脚本,递归地遍历文件夹和文件,最后在它们上运行文件,以检查它们是否可能从某个备份中完全恢复。 (recovered files play, and are identified as mp3 or other audio, non-working files as ASCII-Text) (恢复的文件播放,并被识别为mp3或其他音频,非工作文件为ASCII-Text)

For now I would just be satisfied with having it go over my test folder structure, print all folders & corresponding files. 现在我只是满足于让它超过我的测试文件夹结构,打印所有文件夹和相应的文件。 (printing them mainly for testing, but also because I would like to log where the script currently is and how far along it is in the end, to verify what has been processed) (打印它们主要用于测试,但也因为我想记录脚本当前所在的位置以及它到底有多远,以验证已处理的内容)

I tried using 2 for loops, one for the folders, then one for the files. 我尝试使用2 for循环,一个用于文件夹,然后一个用于文件。 (so that ideally it would take 1 folder, then list the files in there (or potentially delve into subfolders) and below each folder only give the files in that subfolders, then moving on to the next. Such as: (理想情况下,它需要1个文件夹,然后列出那里的文件(或可能深入研究子文件夹),每个文件夹下面只提供该子文件夹中的文件,然后继续下一个文件夹。例如:

Folder1  
- File 1  
- File 2  
    -- Subfolder  
    -- File3  
    -- File4  
Folder2  
- File5  

However this doesn't seem to work in the ways (such with for loops) that are normally proposed. 然而,这似乎并不适用于通常提出的方式(例如for循环)。 I got as far as using "find . -type d" for the directories and "find . -type f" or "find * -type f" (so that it doesn't go in to subdirectories) However, when just printing the paths/files in order to check if it ran as I wanted it to, it became obvious that that didn't work. 我为目录使用“find.-type d”并且“find。-type f”或“find * -type f”(因此它不会进入子目录)但是,当只是打印时路径/文件,以检查它是否按我的意愿运行,很明显,这不起作用。

It always seemed to first print all the directories (first loop) and then all the files (second loop). 它似乎总是首先打印所有目录(第一个循环),然后是所有文件(第二个循环)。 For keeping track of what it is doing and for making it easier to know what was checked/recovered I would like to do this in a more orderly fashion as explained above. 为了跟踪它正在做什么以及为了更容易知道检查/恢复的内容,我希望以更有序的方式执行此操作,如上所述。 So is it that I just did something wrong, or is this maybe a general limitation of the for loop in bash? 那么我只是做错了什么,或者这可能是bash中for循环的一般限制?

Another problem that could be related: Although assigning the output of find to an array seemed to work, it wasn't accessible as an array ... 另一个可能相关的问题是:尽管将find的输出分配给一个数组似乎有效,但它无法作为数组访问...

Example for loop: 循环示例:
for folder in '$(find . -type d)' ; 对于'$(find.-type d)'中的文件夹; do
echo $folder echo $文件夹
let foldercounter++ 让foldercounter ++
done DONE

Arrays: folders=("$(find . -type d)") 数组:folders =(“$(find.-type d)”)
#As far as I know this should assign the output as an array #据我所知,这应该将输出分配为数组
#However, it is not really assigned properly somehow as #但是,它并没有真正以某种方式正确分配
echo "$folders[1]" echo“$ folders [1]”
# does not work (quotes necessary for spaces) #不起作用(空格必需的引号)

For going over some recovered data, I am working on a script that recursively goes through folders & files and finally runs file on them, to check if they are likely fully recovered from a certain backup or not. 为了查看一些恢复的数据,我正在编写一个脚本,递归地遍历文件夹和文件,最后在它们上运行文件,以检查它们是否可能从某个备份中完全恢复。 (recovered files play, and are identified as mp3 or other audio, non-working files as ASCII-Text) (恢复的文件播放,并被识别为mp3或其他音频,非工作文件为ASCII-Text)

If you want to run file on every file and directory in the current directory, including its subdirectories and so on, you don't need to use a Bash for -loop, because you can just tell find to run file : 如果要在当前目录中的每个文件和目录(包括其子目录等)上运行file ,则不需要使用Bash for -loop,因为您可以告诉find运行file

find -exec file '{}' ';'

(The -exec ... ';' option runs the command ... on every matched file or directory, replacing the argument {} with the path to the file.) -exec ... ';'选项在每个匹配的文件或目录上运行命令... ,将参数{}替换为文件的路径。)

If you only want to run file on regular files (not directories), you can specify -type f : 如果您只想在常规文件(而不是目录)上运行file ,则可以指定-type f

find -type f -exec file '{}' ';'

If you (say) want to just print the names of directories, but run the above on regular files, you can use the -or operator to connect one directive that uses -type d and one that uses -type f : 如果您(比如)想要打印目录的名称,但是在常规文件上运行上面的命令,则可以使用-or运算符连接一个使用-type d指令和一个使用-type f指令:

find -type d -print -or -type f -exec file '{}' ';'

Edited to add: If desired, the effect of the above commands can be achieved in pure Bash (plus the file command, of course), by writing a recursive shell function. 编辑添加:如果需要,通过编写递归shell函数,可以在纯Bash(当然还有file命令)中实现上述命令的效果。 For example: 例如:

function foo () {
    local file
    for file in "$1"/* ; do
        if [[ -d "$file" ]] ; then
            echo "$file"
            foo "$file"
        else
            file "$file"
        fi
    done
}
foo .

This differs from the find command in that it will sort the files more consistently, and perhaps in gritty details such as handling of dot-files and symbolic links, but is broadly the same, so may be used as a starting-point for further adjustments. 这与find命令的不同之处在于,它将更加一致地对文件进行排序,并且可能在诸如点文件和符号链接的处理等细节上进行排序,但大致相同,因此可以用作进一步调整的起点。

A find ... -exec ... solution @H.-Dirk Schmitt was referring to might look something like: 一个find ... -exec ...解决方案@ H.-Dirk Schmitt指的可能看起来像:

find . -type f -exec sh -c '
    case $(file "$1") in
    *Audio file*)
        echo "$1 is an audio file"
        ;;
    *ASCII text*)
        echo "$1 is an ascii text file"
        ;;
    esac
' _ {} ';'

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

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