Gzip grande quantidade de arquivos com links simbólicos

Gzip grande quantidade de arquivos com links simbólicos

Eu tenho uma pasta contendo uma grande quantidade de arquivos com links simbólicos. Cada um desses arquivos tem cerca de 10 a 11 GB (arquivos fastq para ser específico). Eles vêm de uma variedade de pastas de origem, mas me certifiquei de que houvesse apenas um nível de links simbólicos.

Estou tentando compactá-los simplesmente fazendo:

gzip *.fastq

Isso resulta em um monte de

too many levels of symbolic links

E assim falha.

No entanto, quando eu faço:

for i in `ls | egrep *.fastq$`; do gzip -c $i > $i.gz; done;

funciona. Minha pergunta é simples. Qual é a diferença entre eles? AFAIK, a única diferença é que a segunda abordagem inicia um novo processo gzip para cada arquivo, enquanto a primeira deve fazer tudo em um processo. O gzip pode lidar apenas com um arquivo com link simbólico por vez? Fazer o mesmo em uma pasta de teste com arquivos normais funciona nos dois sentidos.

Responder1

Uma verificação rápida da fonte gzip (especificamente, gzip 1.6 incluído no Ubuntu 14.04), mostra que o comportamento observado vem da funçãoopen_and_stat, começando na linha 1037 do gzip.c:

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;
}

Observe que a linha de comentário afirma que gzip não seguirá links simbólicos, a menos que seja chamado com os sinalizadores -c ou -f e dentro de #if ... #endif a variável errno esteja definida como ELOOP (muitos links simbólicos encontrados) se o arquivo a ser compactado é na verdade um link simbólico.

Agora, na página de manual do gzip(1), os sinalizadores -c e -f são:

   -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.

Juntando tudo e voltando à pergunta original:

  • O primeiro exemplo falha porque está tentando compactar o link simbólico real (mesmo que sejanãoum loop de link real)
  • O segundo usa o sinalizador -c, portanto, lê o conteúdo do arquivo original e, em seguida, grava a saída compactada em stdout, para que seja bem-sucedido.
  • Um terceiro cenário é usar -f em vez de -c. Neste caso, o gzip não reclama ao tentar compactar um link simbólico, mas ao descompactá-lo ele se torna um arquivo normal, conforme mostrado:
$ ls -l
total 4
-rw-rw-r-- 1 x86tux x86tux 13 16 de junho 13:10 realfile.txt
lrwxrwxrwx 1 x86tux x86tux 12 16 de junho 23:40 link simbólico.txt -> arquivo real.txt
$ gzip link simbólico.txt
gzip: symlink.txt: Muitos níveis de links simbólicos
$ gzip -f link simbólico.txt
$ ls -l
total 8
-rw-rw-r-- 1 x86tux x86tux 13 16 de junho 13:10 realfile.txt
-rw-rw-r-- 1 x86tux x86tux 45 16 de junho 13:10 symlink.txt.gz
$ gunzip link simbólico.txt.gz
$ ls -l
total 8
-rw-rw-r-- 1 x86tux x86tux 13 16 de junho 13:10 realfile.txt
-rw-rw-r-- 1 x86tux x86tux 13 16 de junho 13:10 link simbólico.txt
$md5sum*
618f486e0225d305d16d0648ed44b1eb arquivo real.txt
618f486e0225d305d16d0648ed44b1eb link simbólico.txt

Responder2

O processo único por parte do arquivo pode prejudicar alguns se houver alguma possibilidade de afunilar sua operação, mas com 10 a 11 gigabytes é muito difícil imaginar qualquer cenário em que seja a execchamada gzipque atrapalhe o progresso.

Na mesma linha, se eles fossem um monte de arquivos pequenos, gzipprovavelmente não seriam capazes de compactá-los, tendo menos dados para comparar por arquivo, mas, novamente, de 10 a 11 gigabytes por operação de compactação, isso não será um problema .

Descobrir a causa do erro seria interessante, eu acho. Eu sugeriria tentar aplicar lsofa um gzippid em segundo plano e descobrir o que está acontecendo.

informação relacionada