多くのシンボリックリンクファイルを含むフォルダがあります。ファイルサイズはすべて10〜11GBです(特にfastqファイル)。さまざまなソースフォルダからインポートされますが、シンボリックリンクレベルは1つだけです。
単に以下を実行して圧縮しようとしています。
gzip *.fastq
これはいくつかの結果をもたらします。
too many levels of symbolic links
だから失敗しました。
しかし、私がこうすれば:
for i in `ls | egrep *.fastq$`; do gzip -c $i > $i.gz; done;
実際に働く。私の質問は簡単です。それらの違いは何ですか? AFAIKの唯一の違いは、2番目の方法は各ファイルに対して新しいgzipプロセスを開始することですが、最初の方法は1つのプロセスですべての操作を実行する必要があることです。 gzipは一度に1つのシンボリックリンクファイルしか処理できませんか?通常のファイルを含むテストフォルダで同じことを行うと、双方向で動作します。
答え1
gzipソースコード(特にUbuntu 14.04に含まれているgzip 1.6)をすばやく調べると、観察された動作がこの関数に由来することがわかります。公開と統計、gzip.cの1037行目から始めます。
static int
open_and_stat (char *name, int flags, mode_t mode, struct stat *st)
{
int fd;
/* Refuse to follow symbolic links unless -c or -f. */
if (!to_stdout && !force)
{
if (HAVE_WORKING_O_NOFOLLOW)
flags |= O_NOFOLLOW;
else
{
#if HAVE_LSTAT || defined lstat
if (lstat (name, st) != 0)
return -1;
else if (S_ISLNK (st->st_mode))
{
errno = ELOOP;
return -1;
}
#endif
}
}
fd = OPEN (name, flags, mode);
if (0 <= fd && fstat (fd, st) != 0)
{
int e = errno;
close (fd);
errno = e;
return -1;
}
return fd;
}
コメントアウトされた行では、-cまたは-fフラグを使用して呼び出されない限り、gzipはシンボリックリンクに従わず、#if ...を表します。圧縮するファイルは実際にシンボリックリンクです。
gzip(1) のマニュアルページで、-c フラグと -f フラグは次のようになります。
-c --stdout --to-stdout Write output on standard output; keep original files unchanged. If there are several input files, the output consists of a sequence of independently com‐ pressed members. To obtain better compression, concatenate all input files before compressing them. -f --force Force compression or decompression even if the file has multiple links or the corresponding file already exists, or if the compressed data is read from or written to a terminal. If the input data is not in a format recognized by gzip, and if the option --stdout is also given, copy the input data without change to the standard output: let zcat behave as cat. If -f is not given, and when not running in the background, gzip prompts to verify whether an existing file should be overwritten.
すべてをまとめて元の質問に戻ると、次のようになります。
- 最初の例は、実際のシンボリックリンクを圧縮しようとするため失敗します。いいえ実際のリンクループ)
- 2番目は-cフラグを使用しているため、元のファイルの内容を読み取り、圧縮された出力をstdoutに書き込むことで成功します。
- 3番目のケースは、-cの代わりに-fを使用することです。この場合、gzipはシンボリックリンクを圧縮しようとすると文句を言うことはありませんが、解凍した後は次のように一般的なファイルになります。
$ls -l 合計4個 -rw-rw-r-- 1 x86tux x86tux 13 6月16日 13:10 realfile.txt lrwxrwxrwx 1 x86tux x86tux 12 6月16日 23:40 Symlink.txt -> realfile.txt $gzip シンボリックリンク.txt gzip:Symlink.txt:シンボリックリンクレベルが多すぎます。 $gzip -f シンボリックリンク.txt $ls -l 合計8個 -rw-rw-r-- 1 x86tux x86tux 13 6月16日 13:10 realfile.txt -rw-rw-r-- 1 x86tux x86tux 45 6月16日 13:10 symlink.txt.gz $gunzipシンボリックlink.txt.gz $ls -l 合計8個 -rw-rw-r-- 1 x86tux x86tux 13 6月16日 13:10 realfile.txt -rw-rw-r-- 1 x86tux x86tux 13 6月16日 13:10 Symlink.txt $md5sum* 618f486e0225d305d16d0648ed44b1eb 物理ファイル.txt 618f486e0225d305d16d0648ed44b1ebシンボリックリンク.txt
答え2
ファイルごとに1つのプロセスが作業を妨げる可能性がある場合は少し害を及ぼす可能性がありますが、10〜11 GBではexec
進行が妨げられるシナリオを想像するのは難しいですgzip
。
同様に、小さなファイルの束の場合、gzip
各ファイルの比較するデータが少ないため、圧縮できない可能性がありますが、圧縮操作ごとに10〜11 GBを使用すると圧縮できません。問題。
エラーの原因を突き止めるのは興味深いと思いました。lsof
背景PIDに適用しgzip
、何が起こっているのかを調べることをお勧めします。