Extrai arquivos com cpio onde um ou mais caminhos podem conter espaços

3

Nós temos um arquivo cpio que foi criado gerando um arquivo que contém uma lista de caminhos absolutos a serem incluídos no arquivo. (um caminho absoluto por linha de um arquivo de texto simples) O comando para gerar o arquivo é essencialmente:

cat list-of-files | cpio -ocvB > preserved.cpio

Mais tarde, precisamos extrair arquivos desse arquivo. Novamente queremos usar um arquivo que contenha uma lista de arquivos a serem extraídos (algum subconjunto de todos os arquivos no arquivo, novamente com o formato de um caminho absoluto por linha de um arquivo de texto simples).

cpio -icuBdmv 'cat files-to-extract' < preserved.cpio

Isso funciona bem, a menos que um dos caminhos contenha um espaço. Gerar o arquivo é bom, mas ao extrair os arquivos, qualquer arquivo com um espaço no nome é ignorado silenciosamente. Todos os outros caminhos em files-to-extract foram extraídos com sucesso.

Eu tenho jogado no console tentando encontrar uma maneira de contornar isso, mas sem sucesso. Se eu especificar um único arquivo com um espaço no nome e encapsulá-lo entre aspas, o arquivo será extraído com êxito:

# This extracts the file successfully
cpio -icuBdmv "/foo/bar/some file.txt" < preserved.cpio

Assim, eu poderia ler files-to-extract em um loop e extrair cada arquivo um de cada vez, mas esses arquivos podem ser grandes (vários GB), então isso é terrivelmente lento.

Eu tentei algumas coisas para, de alguma forma, tentar escapar dos espaços em caminhos de arquivo ou citar cada valor de caminho, mas nada que eu tentei funcionou.

# Still skips the file with spaces:
cpio -icuBdmv 'cat files-to-extract | sed 's/ /\ /'' < preserved.cpio
# Extracts no files, even the ones without spaces:
cpio -icuBdmv 'cat files-to-extract | sed 's/\(.*\)/""/'' < preserved.cpio

Seria realmente bom poder fazer essa extração com uma única execução de cpio em vez de ter que fazer um loop e extrair um arquivo de cada vez. Tenho certeza de que este é apenas um problema de como eu estou fornecendo esses valores para o cpio, mas para a vida de mim não consigo entender o porquê.

Provavelmente não relevante, mas apenas por completude: isto é no CentOS 7.2, usando o GNU cpio 2.11

    
por Michael L. 27.05.2016 / 02:42

2 respostas

2

cpio tem uma opção -E ( --pattern-file ), que permite ler a lista de nomes de arquivos de um arquivo, em vez de (ou bem) fornecer os nomes de arquivos na linha de comando. Por exemplo:

cpio -icuBdmv -E files-to-extract < preserved.cpio

cpio também tem -F para especificar um nome de arquivo (em vez de usar stdin / stdout). -I e -O são semelhantes, mas funcionam em vez de stdin ou stdout, respectivamente.

por exemplo. você pode especificar o arquivo com -F e fornecer a lista de arquivos em stdin:

cpio -icuBdmv -F preserved.cpio < files-to-extract 

ou use os dois -E e -F

cpio -icuBdmv -E files-to-extract -F preserved.cpio

BTW, com muitos programas GNU (incluindo cpio , as man pages são quase inúteis, mas estão bem documentadas em arquivos .info. Em algumas distribuições Linux, os docs de informações são frequentemente pacotes separados (por exemplo, no debian, cpio-doc ), então você precisará instalá-los, assim como um leitor de informações (como o GNU info ou pinfo )

de qualquer forma, aqui estão alguns extratos relevantes das páginas cpio info:

-E FILE, --pattern-file=FILE

Read additional patterns specifying filenames to extract or list from FILE. The lines of FILE are treated as if they had been non-option arguments to cpio. This option is used in copy-in mode,

e

-F ARCHIVE, --file=ARCHIVE

Archive filename to use instead of standard input or output. To use a tape drive on another machine as the archive, use a filename that starts with HOSTNAME:, where HOSTNAME is the name or IP address of the machine. The hostname can be preceded by a username and an @ to access the remote tape drive as that user, if you have permission to do so (typically an entry in that user's ~/.rhosts file).

    
por 27.05.2016 / 14:21
3

Os espaços nos nomes dos arquivos podem ser complicados, mas acho que isso pode ajudar.

Em vez de cat ing seus arquivos para extrair, tente alimentá-lo através de xargs substituindo o caractere NULL por EOL.

Algo como

tr '\n' '
tr '\n' '%pre%' < list-of-files | xargs -0 -I{} sh -c 'cpio -icuBdmv "{}" < preserved.cpio'
' < list-of-files | xargs -0 -I{} sh -c 'cpio -icuBdmv "{}" < preserved.cpio'

deve fazer o truque.

    
por 27.05.2016 / 07:09

Tags