linux查找文件中空格及,关于linux:查找文件并对它们进行tar(带空格)

好吧,这么简单的问题。我正在编写一个简单的备份代码。它工作得很好,除非文件中有空格。以下是我查找文件并将其添加到tar存档的方式:

find . -type f | xargs tar -czvf backup.tar.gz

问题是当文件名中有空间时,因为tar认为它是一个文件夹。基本上,有没有一种方法可以在find的结果周围添加引号?或者用另一种方法来解决这个问题?

使用find ... | xargs ...的最佳方法是在每个:find -print0 ... | xargs -0 ...上使用-print0/-0参数。这将导致文件名被一个空字符分隔,这意味着文件名中可以有空格、换行符或其他奇怪的内容,而且它仍然有效。

这样使用xargs和tar有一个问题:当您有大量文件时,xargs将重复调用tar-c,这将不断覆盖您的归档文件,结果是您不会拥有您期望的所有文件。请参阅下面更详细的解释和我的答案。

使用此:

find . -type f -print0 | tar -czvf backup.tar.gz --null -T -

它将:

处理带有空格、换行符、前导破折号和其他功能的文件

处理无限数量的文件

不会重复覆盖backup.tar.gz,就像在xargs中使用tar -c一样,当您有大量文件时会这样做。

还可以看到:

GNU沥青手册

我怎样才能从stdin构建一个tar?,搜索空值

如果你想先把你的发现通过SED传输几次,你会怎么做?例如查找。-打印0 SED/备份/D tar….

请注意,如果有多个条件,则需要添加括号。否则,-print0仅适用于最后一个表达式。如find . \( -type f -o -name '*.c' \) -print0 | ...。

为了好玩,这里有一个使用cygwin的windows版本:c:\cygwin\bin\find . -regextype posix-egrep -regex '.*(sln^|vcxproj^|filters)$' -print0 | c:\cygwin\bin\tar -cvf MS_Projects.tar --null -T -

@史蒂夫,你能解释一下在tar命令末尾的"-"选项吗?我在GNU TAR的主页上找不到它。

当然,它是-T的一个参数,它的意思是从标准输入中读取文件名:如果为`--file s from',(即,指定--files from=-或-t-)指定一个破折号作为文件名,则从标准输入中读取文件名。

--null是什么?

@tommy.carstensen它处理由-print0arg生成的以空分隔的文件名到find,这使得所有这些都能够处理带有空格、换行符等的文件名。

还有另一种方法可以实现你想要的。基本上,

使用find命令将路径输出到您要查找的任何文件。将stdout重定向到您选择的文件名。

然后使用-t选项tar,该选项允许它获取文件位置列表(使用find!创建的位置)。

find . -name"*.whatever"> yourListOfFiles

tar -cvf yourfile.tar -T yourListOfFiles

这对换行的文件名无效

这里有一个关于如何用换行符处理文件名的答案:superuser.com/a/513319/151261

试运行:

find . -type f | xargs -d"

" tar -czvf backup.tar.gz

为什么不:

tar czvf backup.tar.gz *

当然,先使用find,然后使用xargs是很聪明的,但这是很难做到的。

更新:Porges评论说,我认为一个查找选项比我的答案更好,或者另一个:find -print0 ... | xargs -0 ....。

我的完整代码将只备份在过去一天中修改过的项目。因为它是每日备份,所以我不想重复保存文件大小的信息(我也每15天进行一次完整备份)。

为了使这个问题更好,我会问一个关于"可靠地同时使用find、xargs和tar"的问题。您的标题和问题并没有真正指定您需要查找和xargs,但您确实需要。

如果文件列表太长,xargs ... tar c ...将覆盖创建的第一个存档,xargs将第二次执行tar!为了避免覆盖,您可以使用xargs -x,但是归档可能不完整。另一种可能是先使用tar c ...,然后可能重复使用tar r ...。(我对可靠性的贡献:)

如果您有多个文件或目录,并且希望将它们压缩到独立的*.gz文件中,则可以执行此操作。可选-type f -atime。

find -name"httpd-log*.txt" -type f -mtime +1 -exec tar -vzcf {}.gz {} \;

这会压缩

httpd-log01.txt

httpd-log02.txt

httpd-log01.txt.gz

httpd-log02.txt.gz

另一个解决方案如下所示:

find var/log/ -iname"anaconda.*" -exec tar -cvzf file.tar.gz {} +

为什么不试试这样的东西:tar cvf scala.tar `find src -name *.scala`。

最好的解决方案似乎是创建一个文件列表,然后存档文件,因为您可以使用其他源并对该列表执行其他操作。

例如,这允许使用列表计算正在存档的文件的大小:

#!/bin/sh

backupFileName="backup-big-$(date +"%Y%m%d-%H%M")"

backupRoot="/var/www"

backupOutPath=""

archivePath=$backupOutPath$backupFileName.tar.gz

listOfFilesPath=$backupOutPath$backupFileName.filelist

#

# Make a list of files/directories to archive

#

echo""> $listOfFilesPath

echo"${backupRoot}/uploads">> $listOfFilesPath

echo"${backupRoot}/extra/user/data">> $listOfFilesPath

find"${backupRoot}/drupal_root/sites/" -name"files" -type d >> $listOfFilesPath

#

# Size calculation

#

sizeForProgress=`

cat $listOfFilesPath | while read nextFile;do

if [ ! -z"$nextFile" ]; then

du -sb"$nextFile"

fi

done | awk '{size+=$1} END {print size}'

`

#

# Archive with progress

#

## simple with dump of all files currently archived

#tar -czvf $archivePath -T $listOfFilesPath

## progress bar

sizeForShow=$(($sizeForProgress/1024/1024))

echo -e"

Running backup [source files are $sizeForShow MiB]

"

tar -cPp -T $listOfFilesPath | pv -s $sizeForProgress | gzip > $archivePath

一个内衬?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值