好的,这里有一个简单的问题。我正在编写一个简单的备份代码。它能正常工作,但如果文件名中有空格就会出现问题。这是我查找文件和将它们添加到tar归档文件的方式:
find . -type f | xargs tar -czvf backup.tar.gz
问题出现在文件名中有空格时,因为tar会将其认为是一个文件夹。基本上,我是否可以在find的结果周围添加引号?或者有其他方法来解决这个问题吗?
find . -type f -print0 | tar -czvf backup.tar.gz --null -T -
它将会:
tar -c
和 xargs
时在拥有大量文件时反复覆盖你的备份.tar.gz 文件另请参见:
find . \( -type f -o -name '*.c' \) -print0 | ...
- nimrodmc:\cygwin\bin\find . -regextype posix-egrep -regex '.*(sln^|vcxproj^|filters)$' -print0 | c:\cygwin\bin\tar -cvf MS_Projects.tar --null -T -
- Jon有另一种实现你想要的方式。基本上,
Then tar with the -T option which allows it to take a list of file locations (the one you just created with find!)
find . -name "*.whatever" > yourListOfFiles
tar -cvf yourfile.tar -T yourListOfFiles
tar
之前,我需要对其进行编辑。tar
的第一个man
页面似乎提供了可用选项的概述(所以我就停在那里了),但实际上还有很多选项。 - undefined请尝试运行以下命令:
find . -type f | xargs -d "\n" tar -czvf backup.tar.gz
为什么不:
tar czvf backup.tar.gz *
使用find和xargs确实很聪明,但你是以一种较困难的方式来做。
更新:Porges已经发表评论,提供了一个更好的答案。它比我之前给出的答案或其他答案更好:find -print0 ... | xargs -0 ....
xargs ... tar c ...
将覆盖第一个创建的归档文件,并且 xargs
将再次执行 tar
!为了避免覆盖,您可以使用 xargs -x
,但是这样可能会导致归档文件不完整。另一种选择是先使用 tar c ...
,然后可能反复使用 tar r ...
。(这是我对可靠性的贡献 :) - pabouk - Ukraine stay strong*.gz
文件,您可以这样做。可选参数 -type f -atime
。find -name "httpd-log*.txt" -type f -mtime +1 -exec tar -vzcf {}.gz {} \;
httpd-log01.txt
httpd-log02.txt
to
httpd-log01.txt.gz
httpd-log02.txt.gz
我想在@Steve Kehlet的帖子中添加评论,但需要50个声望(RIP)。
对于通过众多谷歌搜索找到此帖子的任何人,我找到了一种方法,不仅可以在给定时间范围内找到特定文件,而且还可以不包括导致压缩错误的相对路径或空格。(非常感谢Steve。)
find . -name "*.pdf" -type f -mtime 0 -printf "%f\0" | tar -czvf /dir/zip.tar.gz --null -T -
.
相对目录
-name "*.pdf"
查找pdf(或任何文件类型)
-type f
查找的类型为文件
-mtime 0
查找创建时间在过去24小时之内的文件
-printf "%f\0"
普通的-print0
或 -printf "%f"
对我无用。从man页中得知:
这种引用方式与GNU ls相同。这不是与-ls和-fls使用的引用机制相同。如果您能决定find输出使用的格式,通常最好使用'\0'作为终止符而不是使用换行符,因为文件名可能包含空格和换行符。
-czvf
创建档案,将档案过滤通过gzip,详细列出处理的文件,档案名称编辑2019-08-14: 我还想补充一点,我也可以在我的评论中使用基本上相同的命令,只是直接使用tar本身:
tar -czvf /archiveDir/test.tar.gz --newer-mtime=0 --ignore-failed-read *.pdf
如果今天没有新的PDF文件,需要使用--ignore-failed-read
。
tar cvf scala.tar `find src -name *.scala`
。这里还有另一种解决方案,可以参考这里:
find var/log/ -iname "anaconda.*" -exec tar -cvzf file.tar.gz {} +
#!/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 "\nRunning backup [source files are $sizeForShow MiB]\n"
tar -cPp -T $listOfFilesPath | pv -s $sizeForProgress | gzip > $archivePath
对于几个解决方案(包括您自己的测试)有一个重要的警告:
当您执行:anything | xargs something
xargs 将尝试在“something”之后“尽可能多地添加参数”,但是这样您可能会得到多个“something”的调用。
因此,您的尝试:find ... | xargs tar czvf file.tgz 可能会在每次xargs调用tar时覆盖“file.tgz”,最终只保留最后一次调用!(所选解决方案使用GNU -T特殊参数来避免该问题,但并非每个人都有可用的GNU tar)
您可以改为:
find . -type f -print0 | xargs -0 tar -rvf backup.tar
gzip backup.tar
在Cygwin上出现问题的证明:
$ mkdir test
$ cd test
$ seq 1 10000 | sed -e "s/^/long_filename_/" | xargs touch
# create the files
$ seq 1 10000 | sed -e "s/^/long_filename_/" | xargs tar czvf archive.tgz
# will invoke tar several time as it can'f fit 10000 long filenames into 1
$ tar tzvf archive.tgz | wc -l
60
# in my own machine, I end up with only the 60 last filenames,
# as the last invocation of tar by xargs overwrote the previous one(s)
# proper way to invoke tar: with -r (which append to an existing tar file, whereas c would overwrite it)
# caveat: you can't have it compressed (you can't add to a compressed archive)
$ seq 1 10000 | sed -e "s/^/long_filename_/" | xargs tar rvf archive.tar #-r, and without z
$ gzip archive.tar
$ tar tzvf archive.tar.gz | wc -l
10000
# we have all our files, despite xargs making several invocations of the tar command
find .... | xargs grep "regex"
find ..... | xargs grep "regex" /dev/null
/dev/null
,在那里它找不到任何东西,以及在其后由xargs附加的文件名
),因此当匹配“regex”时总是显示文件名。否则,您可能会出现最后的结果显示匹配项而没有文件名。
find ... | xargs ...
命令的最佳方法是每个命令都使用-print0/-0
参数:find -print0 ... | xargs -0 ...
。 这将使文件名由空字符分隔,这意味着您可以在文件名中包含空格、换行符或其他奇怪的字符,并且此命令仍能正常工作。 - porges