
Как создать рекурсивный цикл по пути и получить последний созданный 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