您已经有一个有效的find | xargs ls,它会为您提供排序后的文件列表,最新的优先。 (正如@sjsam 指出的那样,假设您的文件名都不包含换行符。)您可以使用 bash 的process-substitution 功能将该列表放入文件中,每行一个条目,以便它可以是 read by a while ... read loop。然后,您可以在备份成功后立即退出循环。
# vvvvvvvvvvvvvvvvvvvvvv get the next filename into $tarname
while IFS= read -r tarname
do
tar -xf "$tarname" && break
# ^^^^^^^^ done with the loop if tar succeeds
done < <(find /config/config_*.tar -maxdepth 1 -type f -size +1k -print0 | xargs -0 ls -hat)
# ^ ^^^^---- the process substitution
# |
# +--------- the redirection from the process subsitution
请注意,您确实需要< <(...),而不仅仅是<(...)。
(顺便问一下,你需要ls -hat,还是ls -t也需要?)
编辑!又名Take 3
我受到@sjsam 评论的启发,写了ls0,这是一个ls 替代品,可以提供以NULL 结尾的输出。如果发现任何错误,请检查并提交问题!它在 Cygwin 上使用 Perl 5.22 进行了测试,但应该适用于大多数 Perl 5。它是一个单独的文件——安装时,将ls0 放在你的路径中,chmod ugo+x ls0。
使用ls0,上面的技术可以从容处理奇怪命名的文件:
while IFS= read -r -d '' tarname
do
tar -xf "$tarname" && break
done < <(find /config/config_*.tar -maxdepth 1 -type f -size +1k -print0 | ls0 -t)
(正如@sjsam 所说,-d '' 在功能上等同于-d $'\0')
Take 2 page sjsam links 建议使用 perl 而不是 ls 对文件名进行排序。这样您就可以处理包含换行符或其他奇怪字符的文件名。
这是该技术的一个示例(不是 OP 问题的答案)。我已经使用包含换行符的文件名对其进行了测试。以下代码打印当前目录中的 *.tar 文件,最新的在前。此示例在每个文件名之前和之后打印一个斜杠,以便您可以看到带有换行符的文件名被正确处理。在 cygwin、bash 4.3.46、perl 5.22.2 上测试。
perl -e 'opendir(my $dirh, "."); print(join "\0", sort { -M $a <=> -M $b } grep /.tar$/, readdir($dirh))' \
| while IFS= read -r -d $'\0' name
do
printf "/%s/\n" "$name"
done
因此,将所有这些放在一起以获得 (1) 回答 OP 的问题并且 (2) 对具有奇怪内容的文件名具有鲁棒性的代码:
perl -e 'opendir(my $dirh, "."); print(join "\0", sort { -M $a <=> -M $b } grep /.tar$/, readdir($dirh))' \
| while read -r -d $'\0' tarname
do
tar -xf "$tarname" && break
done
或者,使用进程替换,
while IFS= read -r -d $'\0' tarname
do
tar -xf "$tarname" && break
done < <(perl -e 'opendir(my $dirh, "."); print(join "\0", sort { -M $a <=> -M $b } grep /.tar$/, readdir($dirh))')
很简单,对吧? ;)
来源: