обновлять

обновлять

Как создать рекурсивный цикл по пути и получить последний созданный tar.gzфайл в каждом каталоге?

Я хочу запустить tar -tvf file.tar.gzпоследний созданный файл в каждом каталоге

Все tar.gzфайлы находятся на втором уровне каталога. Таким образом, максимальная глубина цикла равна 2.

Этот скрипт выведет только каждый каталог

cd $base_dir
find . -type d -printf '%f\n'

Базовый каталог /var/www/bakи все файлы tar.gz расположены следующим образом:

/var/www/bak/site1/www/file.tar.gz
/var/www/bak/site1/db/file.tar.gz
/var/www/bak/site2/www/file.tar.gz
/var/www/bak/site2/db/file.tar.gz

обновлять

find_tarballs (){
    cd $base_dir
    find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD}/\"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1
}

filesize (){
    ls -lh $1 | awk -F " " {'print $5'}
}

output="$(find_tarballs)"
set -- $output
shift
for tarball; do
    echo "$tarball"
    if [ ${tarball##*.} = 'gz' ]; then
        list="$(tar -tzf $tarball)"
        echo "Filesize: $(filesize $tarball), Files: $(echo "$list" | wc -l)\n"
        echo 'Press ENTER to list files...'
        read key
        echo "$list"
    else
        echo "Filesize: $(filesize $tarball)"
    fi
    echo ''
done

решение1

Предполагая, что ваши пути не содержат пробелов и символов новой строки:

find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1

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

Чтобы просмотреть содержимое tar-архивов, предполагая, что их имена файлов также не содержат пробелов и символов новой строки:

find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1 | tr ' ' / | xargs -n 1 tar tvf

заменит пробел, разделяющий путь от имени файла, на «/» и передаст результат в , xargsкоторый будет запущен tar tvfдля каждого файла.

Для вывода подсказок между каждым tar-архивом добавьте -pк xargsкоманде:

find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1 | tr ' ' / | xargs -p -n 1 tar tvf

решение2

С помощью zsh, в типичном режиме «только для записи»:

for dir (*/*(N/)) (){(($#)) && tar tvf $1} $dir/*.tar.gz(Nom[1])
  • for var (values) cmd: краткая формаfor var in values; do cmd; done
  • (N/), (Nom[1]): глобальные квалификаторы
    • N: расширяется до нуля, если совпадений нет (nullglob)
    • /: только каталоги
    • om: сортировать по времени изменения (сначала новые)
    • [1]: только первое совпадение
  • (){...} args: анонимные функции со своими аргументами.

С помощью инструментов GNU (по-прежнему не делая предположений о том, какие байты могут содержать имена файлов, но проходя по скрытым каталогам и включая скрытые tar.gzфайлы) и любой оболочки типа Bourne эквивалент может быть таким:

LC_ALL=C find . -mindepth 3 -maxdepth 3 -name '*.tar.gz' -printf '%T@:%p\0' |
  sort -zn | LC_ALL=C awk -v RS='\0' -v ORS='\0' '
    {match($0, ":((.*)/.*)", parts); newest[parts[2]] = parts[1]}
    END {for (dir in newest) print newest[dir]}' |
    xargs -r0n1 tar tvf        

Связанный контент