ファイルを検索してtarで(スペースを入れて)


110

わかりました、とても簡単な問題です。簡単なバックアップコードを作成しています。ファイルにスペースが含まれている場合を除き、正常に動作します。これは、ファイルを見つけてtarアーカイブに追加する方法です。

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

問題は、ファイルの名前にスペースが含まれている場合です。これは、tarがフォルダーと見なしているためです。基本的に、findの結果を引用符で囲む方法はありますか?またはこれを修正する別の方法?


12
使用する最良の方法find ... | xargs ...は、それぞれに-print0 / -0パラメータを使用することですfind -print0 ... | xargs -0 ...。これにより、ファイル名がnull文字で区切られます。つまり、ファイル名にスペースや改行などの奇妙な要素を含めることができ、ファイル名は引き続き機能します。
ポルジェス、

8
多数のファイルがある場合、xargsとtarをこのように使用すると問題が発生します。xargsはtar -cを繰り返し呼び出し、アーカイブを上書きし続けます。その結果、期待するすべてのファイルがなくなります。 。参照してください。この詳細な説明私の答え下記を。
Steve Kehlet

回答:


217

これを使って:

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

そうなる:

  • スペース、改行、先頭のダッシュ、その他の面白さのあるファイルを処理する
  • 無制限の数のファイルを処理する
  • 多数のファイルがある場合にtar -cwith xargsを使用する場合のように、backup.tar.gzを繰り返し上書きしない

こちらもご覧ください:


1
最初に数回sedを使用して検索結果をパイプ処理したい場合、これをどのように行いますか?たとえばを見つけます。-print0 | sed / backups / d | tar ....
Brad Parks

8
複数の条件がある場合は、括弧を追加する必要があることに注意してください。それ以外の場合は-print0、最後の式にのみ適用されます。例find . \( -type f -o -name '*.c' \) -print0 | ...
nimrodm

1
楽しみのために、これはcygwinを使用したこれのWindowsバージョンです:c:\cygwin\bin\find . -regextype posix-egrep -regex '.*(sln^|vcxproj^|filters)$' -print0 | c:\cygwin\bin\tar -cvf MS_Projects.tar --null -T -
Jon

1
@Steveは、tarコマンドの最後にある「-」オプションについて説明していただけますか。GNU tarのmanページでは見つかりません。
shaffooo

確かに、これはのパラメータ-Tであり、標準入力からファイル名を読み取ることを意味します。`--files-from 'のファイル名としてダッシュを1つ指定すると(つまり、-files-from = -または
-T-

14

あなたが望むものを達成する別の方法があるかもしれません。基本的に、

  1. findコマンドを使用して、探しているファイルへのパスを出力します。stdoutを選択したファイル名にリダイレクトします。
  2. 次に、-Tオプションを指定してtarを実行すると、ファイルの場所のリスト(findを使用して作成したもの)のリストを取得できます。

    find . -name "*.whatever" > yourListOfFiles
    tar -cvf yourfile.tar -T yourListOfFiles
    

改行を含むファイル名を処理する方法については、ここに回答があります
。superuser.com/ a / 513319/151261

8

実行してみてください:

    find . -type f | xargs -d "\n" tar -czvf backup.tar.gz 

7

何故なの:

tar czvf backup.tar.gz *

確かにfindを使用してからxargsを使用するのは賢明ですが、難しい方法でやっています。

更新:ポルジェスは、私の答えまたは他の答えよりも良い答えだと思う検索オプションでコメントしました: find -print0 ... | xargs -0 ....


私の完全なコードは、過去1日に変更されたアイテムのみをバックアップします。毎日のバックアップなので、ファイルサイズを節約するために繰り返し情報を取得したくありません(15日ごとに完全バックアップも行います)。
Caleb Kester、

これをより良いSOの質問にするために、「find、xargs、およびtarを確実に一緒に使用すること」について質問します。タイトルと質問では、findとxargsが必要であることを実際に指定していませんが、実際にはそうします。
Warren P

xargs ... tar c ...ファイルのリストが長すぎると、最初に作成されたアーカイブが上書きされ、2回目にxargs実行さtarれます。上書きを避けるために使用できますxargs -xが、アーカイブが不完全になる可能性があります。別の方法としては、最初にtar c ...、次におそらく繰り返しtar r ...ます。(信頼性への私の貢献:)
pabouk 2013年

3

複数のファイルまたはディレクトリがあり、それらを独立した*.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



2

@Steve Kehletの投稿にコメントを追加しますが、50人の担当者(RIP)が必要です。

何度もグーグル検索してこの投稿を見つけた人のために、時間範囲を指定した特定のファイルを見つけるだけでなく、相対パスやタールエラーを引き起こす空白を含めない方法を見つけました。(ありがとうございました。)

find . -name "*.pdf" -type f -mtime 0 -printf "%f\0" | tar -czvf /dir/zip.tar.gz --null -T -
  1. . 相対ディレクトリ

  2. -name "*.pdf" PDF(または任意のファイルタイプ)を探す

  3. -type f 検索するタイプはファイルです

  4. -mtime 0 過去24時間に作成されたファイルを探す

  5. -printf "%f\0"通常の-print0OR -printf "%f"は私にはうまくいきませんでした。manページから:

この引用は、GNU lsと同じ方法で実行されます。これは、-lsおよび-flsで使用されるものと同じ引用メカニズムではありません。ファイル名には空白や改行文字を含めることができるため、findの出力に使用する形式を決定できる場合は、改行を使用するよりも、通常、 '\ 0'をターミネータとして使用することをお勧めします。

  1. -czvf アーカイブの作成、gzipによるアーカイブのフィルタリング、処理されたファイルの詳細なリスト、アーカイブ名

編集2019-08-14:追加したいのですが、tar自体を使用するだけで、コメント内で基本的に同じコマンドを使用することもできました:

tar -czvf /archiveDir/test.tar.gz --newer-mtime=0 --ignore-failed-read *.pdf

--ignore-failed-read今日のために新しいPDFがない場合に備えて必要でした。


1

他のソースを使用してリストで他のことを行うことができるので、最善の解決策はファイルリストを作成してからファイルをアーカイブすることです。

たとえば、これにより、リストを使用してアーカイブするファイルのサイズを計算できます。

#!/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

これのための1つのライナー?
ロビノ2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.