ubuntu / linux bash: каталог и подкаталоги для работы с файлами - PullRequest
0 голосов
/ 17 октября 2010

позвольте мне начать с того, что мне нужно; программе дается каталог, затем он проверяет все файлы в каталоге (работает) и делает что-то с файлами (ожидая, пока найдет все файлы для этой части). тогда он будет искать подкаталоги и перезапускать себя для каждого подкаталога.

каталог, с которым я тестирую, выглядит так:

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 ]

6 голосов
/ 17 октября 2010

По какой причине вы не можете использовать find для этого?Вставьте нужную для каждого файла операцию в свой собственный скрипт (я назвал его dostufftomyfile.sh ниже), затем выполните:

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

Замена $ dir каталогом верхнего уровня, из которого вы будете искать...

Отредактировано для добавления ... Когда вы пишете сценарий оболочки, убедитесь, что вы вставляете $ @ в двойные кавычки ... например, вам понадобится ваш файл dostufftomyfile.Скрипт sh имеет такую ​​структуру:

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

, если вы не заключите в кавычки $ @, пробелы в именах файлов будут игнорироваться (что, я подозреваю, вам не понадобится): -)

0 голосов
/ 18 октября 2010

У вас есть ошибка "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"
0 голосов
/ 17 октября 2010

Ответ Криса Дж - предпочтительный способ сделать что-то, если вы можете поместить материал для каждого файла в отдельную команду (/ script).Если вы хотите все в одном скрипте, мое любимое заклинание выглядит примерно так:

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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...