更新

更新

如何通过路径进行递归循环并获取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

将找到所有 tarball,在每个包含的目录中运行给定的 shell 片段,并过滤结果,以便为每个目录仅保留一个结果。

要查看 tarball 的内容,假设它们的文件名也不包含空格或换行符:

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

将用“/”替换路径与文件名之间的空格,并将结果传递给xargstar tvf在每个文件上运行的程序。

要在每个 tarball 之间进行提示,请添加-pxargs命令中:

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 的 shell,等价的可能是:

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        

相关内容