用于列出文件的递归 shell 脚本

用于列出文件的递归 shell 脚本

我正在尝试编写一个 shell 脚本,列出目录(和子目录)中某些类型的文件。我正在努力解决递归部分。

这是我所拥有的:

#!/bin/sh

#download dir
DOWNLOADING_DIR=/Users/richard/Downloads

echo "Starting Script..."

for FILE in $DOWNLOADING_DIR/*
do
    if [ -d "$FILE" ]
    then
        echo "...Checking Directory "$FILE
        for DFILE in $FILE/*
        do
            echo "Found file ... $DFILE"
        done
    else
        echo "Found file ... $FILE"
        echo ""
    fi
done

问题是当它找到目录时,它在目录中找不到任何文件名。它只列出子目录名称,而不列出子目录中的文件。它适用于第一个目录中的文件。

我需要这个脚本来搜索 .txt 或 .doc 文件并将它们移动到另一个目录。

答案1

你的脚本是不是递归,因为它不调用自身。

这是一个变体,它以递归方式实现类似的东西:

#!/bin/bash

walk_dir () {
    shopt -s nullglob dotglob

    for pathname in "$1"/*; do
        if [ -d "$pathname" ]; then
            walk_dir "$pathname"
        else
            printf '%s\n' "$pathname"
        fi
    done
}

DOWNLOADING_DIR=/Users/richard/Downloads

walk_dir "$DOWNLOADING_DIR"

该函数walk_dir将目录路径名作为其唯一参数并迭代其内容。如果找到目录,它会递归地调用自身来遍历该子目录。

.txt修改此命令以查找文件名后缀为 或的文件.doc

#!/bin/bash

walk_dir () {    
    shopt -s nullglob dotglob

    for pathname in "$1"/*; do
        if [ -d "$pathname" ]; then
            walk_dir "$pathname"
        else
            case "$pathname" in
                *.txt|*.doc)
                    printf '%s\n' "$pathname"
            esac
        fi
    done
}

DOWNLOADING_DIR=/Users/richard/Downloads

walk_dir "$DOWNLOADING_DIR"

请注意,上面的“文件”实际上指的是不是目录或目录符号链接的任何内容,这可能与目录不同。常规文件。通过在 中设置dotglobnullglobshell 选项bash,我们能够找到隐藏的路径名,并且不必专门测试可能为空的目录。

其变体/bin/sh不关心隐藏名称:

#!/bin/sh

walk_dir () {
    for pathname in "$1"/*; do
        if [ -d "$pathname" ]; then
            walk_dir "$pathname"
        elif [ -e "$pathname" ]; then
            case "$pathname" in
                *.txt|*.doc)
                    printf '%s\n' "$pathname"
            esac
        fi
    done
}

DOWNLOADING_DIR=/Users/richard/Downloads

walk_dir "$DOWNLOADING_DIR"

使用中的globstarexglobshell 选项bash,甚至可以执行以下操作(无需递归)来移动文件:

shopt -s globstar extglob

mv "$DOWNLOADING_DIR"/**/*.@(txt|doc) "$destdir"

...除非结果文件列表太长。匹配**路径名中的斜杠(由 启用globstar),并*.@(txt|doc)匹配以 或 结尾的任何文件名.txt.doc由 启用extglob)。


一种更高效、更便携的方法,可以在某个顶级目录中或下查找文件名后缀为 或 的常规文件.txt,并将它们移动到其他目录:.doc$topdir$destdir

find "$topdir" -type f \( -name '*.txt' -o -name '*.doc' \) \
    -exec mv {} "$destdir" \;

使用 GNUmv你可以让它变得更有效率,

find "$topdir" -type f \( -name '*.txt' -o -name '*.doc' \) \
    -exec mv -t "$destdir" {} +

这种变化会移动批次文件而不是一次一个文件。使用mvwith-v来查看移动的内容,或者添加-printbefore来获取调用的-exec路径名列表。mv

相关内容