如何将文件从最年轻的文件解压到最老的文件,直到在bash中成功
我在一个目录中得到了一个tar文件(备份)列表,需要从最年轻的文件到最老的文件进行解压,直到成功 问题是,有时tar文件会被损坏,需要卸载旧的tar文件 这就是我如何找到最年轻的一个,但不知道如何把这个放进去,同时找到下一个如何将文件从最年轻的文件解压到最老的文件,直到在bash中成功,bash,while-loop,tar,Bash,While Loop,Tar,我在一个目录中得到了一个tar文件(备份)列表,需要从最年轻的文件到最老的文件进行解压,直到成功 问题是,有时tar文件会被损坏,需要卸载旧的tar文件 这就是我如何找到最年轻的一个,但不知道如何把这个放进去,同时找到下一个 tar -xf `find /config/config_*.tar -maxdepth 1 -type f -size +1k -print0 | xargs -0 ls -hat | head -n 1` 提前感谢您已经有了一个正在运行的find | xargs ls
tar -xf `find /config/config_*.tar -maxdepth 1 -type f -size +1k -print0 | xargs -0 ls -hat | head -n 1`
提前感谢您已经有了一个正在运行的
find | xargs ls
,它将首先为您提供文件的排序列表。(正如@sjsam所指出的,这假设您的文件名中没有包含换行符。)您可以使用bash的功能将该列表放入一个文件中,每行一个条目,这样就可以重新创建该列表。然后,您可以在一次备份成功后立即退出循环
# 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
(正如@sjsam所指出的,-d'
在功能上等同于-d$'\0'
)
Take 2建议使用
perl
而不是ls
对文件名进行排序。这样,您就可以处理包含换行符或其他奇怪字符的文件名
下面是该技术的一个示例(不是OP问题的答案)。我用一个包含换行符的文件名对它进行了测试。以下代码首先打印当前目录中的*.tar
文件。此示例在每个文件名前后打印一个斜杠,以便您可以看到带换行符的文件名得到了正确处理。在cygwin、Bash4.3.46和Perl5.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
perl-e'opendir(my$dirh,“.”);打印(连接“\0”、排序{-M$a-M$b}grep/.tar$/、readdir($dirh))'\
|而IFS=read-r-d$'\0'名称
做
printf/%s/\n“$name”
完成
因此,将所有这些放在一起的代码(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
perl-e'opendir(my$dirh,“.”);打印(连接“\0”、排序{-M$a-M$b}grep/.tar$/、readdir($dirh))'\
|读取-r-d$'\0'tarname时
做
tar-xf“$tarname”和break
完成
或者,使用过程替换
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))')
而IFS=read-r-d$'\0'tarname
做
tar-xf“$tarname”和break
完成<下面的脚本就可以了
find /path/to/tarball/folder -type f -name "*.tar" -printf "%A@--%p\0" |
sort -rnz | while read -r -d '' stampedfile
do
tar -xzf "${stampedfile#*--}" >/dev/null 2>&1
[ $? -eq 0 ] && echo "Newest Working Tar: ${stampedfile#*--}" && exit
done
我们所做的
- 使用
find
列出以null结尾的tarball文件,这些文件在自epoch以来的最后一次访问时间(以秒为单位)前加上一个--
,我们稍后将其用作分隔符
- 使用修改时间按降序对文件名进行排序。这就是
--
分隔符的用武之地
- 使用while循环分析以null结尾的排序文件
- 从文件名中删除
时间--
,并尝试将其卸载
- 如果尝试成功,则退出
好东西,但是为什么要对$?
进行笨拙的测试呢?(我假设$0
是一个输入错误)您可以直接在tar
之后&exit
(甚至在读取时,执行echo failure>&2;done
)也可能值得一提的是,这将从失败的tar调用中积累部分结果,这可能不是我们想要的——在这种情况下,在使用第一个成功的文件之前,您可能需要对每个文件执行一次试运行。不过,从这个问题上看,我们不清楚想要什么。@TobySpeight:谢谢你在$?
上的指针。是的!有多种方法可以缩短这个时间。为了便于解释,我放了长一点的。:)Cheerz@sjsam如果tar的名称包含一个-->
?@cxw漂亮的点,则不应该“${stampedfile.*-}”是“${stampedfile.*-}”(最短匹配)吗,合并..理想情况下,分隔符应该是唯一的,它不应该出现在文件名中。它用于分析ls的输出。我使用了第一个版本,因为名称中没有空格。@sjsam签出-现在您不必再分析ls的输出了!你怎么认为?谢谢你的鼓励,这给了我灵感。:)
find /path/to/tarball/folder -type f -name "*.tar" -printf "%A@--%p\0" |
sort -rnz | while read -r -d '' stampedfile
do
tar -xzf "${stampedfile#*--}" >/dev/null 2>&1
[ $? -eq 0 ] && echo "Newest Working Tar: ${stampedfile#*--}" && exit
done