ubuntu / linux bash:遍历目录和子目录来处理文件

时间:2010-10-17 17:47:19

标签: linux bash shell

让我从我需要的东西开始吧;程序被赋予一个目录,然后它将检查目录中的所有文件(工作)并对文件执行操作(等待它可以找到该部分的所有文件)。然后它会查找子目录并为每个子目录重新运行它自己。

我正在测试的目录如下所示:

desktop/test_files/ (starting directory)
desktop/test_files/folder 1/
desktop/test_files/folder 1>folder 2/
desktop/test_files/folder 1>folder 2/<files, 20 or so>
desktop/test_files/folder 3/
desktop/test_files/folder 3/<more files, 20 or so>

文件夹和文件名称中包含空格

输出是:

$ ./x007_shorter.sh Desktop/test_files/

Desktop/test_files/"folder 1"/
Desktop/test_files/folder 1/"folder 2"/
ls: cannot access */: No such file or directory
Desktop/test_files/folder 1/folder 2/"folder 3"/
./x007_shorter.sh: line 4: cd: ./folder 3/: No such file or directory
ls: cannot access */: No such file or directory

这是程序:

#!/bin/bash
function findir {
    newDir=$1
    eval cd $newDir
    ARRAY=( $(ls -d */) )
    declare -a diry
    count=0
    a=0
    while [ $a -lt ${#ARRAY[@]} ]; do
        diry[$count]="${ARRAY[$a]}"
        noSpace=true
        while [ true ]; do
            if [[ ${diry[$count]} == */* ]] ; then
                if [ $noSpace = false ]; then
                diry[$count]="${diry[$count]:0:((${#diry[$count]}-1))}\"/"
                fi
                break
                noSpace=true
            fi
            let "a=$a+1"
            if [ $noSpace = false ]; then
                diry[$count]="${diry[$count]} ${ARRAY[$a]}"
            else
                diry[$count]="\"${diry[$count]} ${ARRAY[$a]}"
            fi
            noSpace=false
        done
        let "count=$count+1"
        let "a=$a+1"
    done
    for a in `seq 1 ${#diry[@]}`; do
        eval cd .$newDir
#        list "${diry[($a-1)]}"
        where=`pwd`
#        eval cd $newDir
        #findir "${diry[($a-1)]}"
        #findir "$where${diry[($a-1)]:1}"
        #Right option won,  echo "${diry[($a-1)]} Vs $where/${diry[($a-1)]}"
        echo "$where/${diry[($a-1)]}"
        findir "./${diry[($a-1)]}"
    done
}
function list {
    input_file_directory=$1
    eval cd $input_file_directory
    ARRAY=( $(find . -maxdepth 1 -type f -print) )
    declare -a files
    count=0
    a=0
    while [ $a -lt ${#ARRAY[@]} ]; do
        files[$count]="${ARRAY[$a]}"
        while [ true ]; do
            if [[ ${ARRAY[(($a+1))]} == ./* ]] ; then
                break
            fi
            if [[ "${ARRAY[(($a+1))]}" == "" ]] ; then
                break
            fi
            let "a=$a+1"
            files[$count]="${files[$count]} ${ARRAY[$a]}"
        done
        let "count=$count+1"
        let "a=$a+1"
    done
    where=`pwd`
    for a in `seq 1 ${#files[@]}`; do
        echo "$where${files[($a-1)]:1}"
        #going to work on each file, just echoing file till lists all files
    done
}

clear
dar=""
if [[ $1 = "" ]]; then
    read -p "Please enter a directory for me to scan" newdir
    dar=$newdir
    list $newdir
    findir $newdir
else
    dar=$1
    list $1
    findir $1
fi

3 个答案:

答案 0 :(得分:6)

你有什么理由不能使用find吗?在你自己的脚本中粘贴你想要的每个文件操作(我在下面称它为dostufftomyfile.sh),然后执行:

find $dir -type f -print0 | xargs -0 dostufftomyfile.sh

将$ dir替换为您要搜索的顶级目录...

已编辑添加... 编写shell脚本时,请确保将$ @放在双引号中...例如,您希望dostufftomyfile.sh脚本具有以下结构:

#!/bin/sh
for f in "$@"
do
    echo "Processing file: $f"
    # Do something to file $f
done

如果你不引用$ @那么文件名中的空格将被忽略(我怀疑你不会想要): - )

答案 1 :(得分:0)

如果您可以将每个文件的内容放在单独的命令(/ script)中,那么Chris J的答案是首选的方法。如果你想要一个脚本中的所有内容,我最喜欢的咒语是这样的:

while IFS="" read -r -d $'\000' file <&3; do
    dostuffwith "$file"
done 3< <(find -x  "$dir" -mindepth 1 -type f -print0)

有关说明和其他一些选项,请参阅BashFAQ #20#89。请注意,这仅适用于bash(即脚本必须以#!/ bin / bash开头)。此外,它按字母顺序处理给定目录的内容,而不是子目录之前的文件。

如果你真的想“手动”逐步浏览文件(即为了更好地控制遍历顺序),我就是这样做的:

#!/bin/bash

process_dir() {
    local -a subdirs=()
    echo "Scanning directory: $1"

    # Scan the directory, processing files and collecting subdirs
    for file in "$1"/*; do
        if [[ -f "$file" ]]; then
            echo "Processing file: $file"
            # actually deal with the file here...
        elif [[ -d "$file" ]]; then
            subdirs+=("$file")
            # If you don't care about processing all files before subfolders, just do:
            # process_dir "$file"
        fi
    done

    # Now go through the subdirs
    for d in "${subdirs[@]}"; do
        process_dir "$d"
    done
}

clear
if [[ -z "$1" ]]; then
    read -p "Please enter a directory for me to scan " dir
else
    dir="$1"
fi
process_dir "$dir"

答案 2 :(得分:0)

由于此

,您收到错误"No such file ....

ARRAY=( $(ls -d */) )

当它的扩展时,带有空格的目录将作为单独的元素存储在数组中。例如Desktop/test_files/folder 1/folder 2/"folder 3"/

在数组中,元素0将是Desktop/test_files/folder,元素1将是1/folder,依此类推。这就是你的脚本无法找到目录的原因。

您可以在分配数组

之前将IFS设置为$'\ n'
OLDIFS=$IFS
IFS=$'\n'
ARRAY=($(ls -d */))
IFS="$OLDIFS"