Extraire des files avec cpio où un ou plusieurs paths peuvent contenir des espaces

Nous avons créé une archive cpio en générant un file contenant une list de paths absolus à inclure dans l'archive. (un path absolu par ligne d'un file text brut) La command pour générer l'archive est essentiellement:

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

Nous devons ensuite extraire des files de cette archive. Nous voulons à nouveau utiliser un file contenant une list de files à extraire (un sous-set de tous les files de l'archive, toujours au format d'un path absolu par ligne d'un file text).

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

Cela fonctionne bien sauf si l'un des paths contient un espace. Générer l'archive est très bien, mais lors de l'extraction des files, tout file avec un espace dans le nom est silencieusement omis. Tous les autres paths dans les files-to-extract sont extraits avec succès.

J'ai joué à la console en essayant de find un moyen de contourner cela, mais en vain. Si je spécifie un seul file avec un espace dans le nom et l'encapsule entre guillemets, le file est extrait avec succès:

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

Je pourrais donc lire les files-to-extract dans une boucle et extraire chaque file un par un, mais ces archives peuvent être volumineuses (plusieurs Go), ce qui est terriblement lent.

J'ai essayé quelques choses d'une manière ou d'une autre essayer d'échapper aux espaces dans les paths de dossier ou de citer chaque valeur de path, mais rien que j'ai essayé a fonctionné.

 # 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/\(.*\)/"\1"/'` < preserved.cpio 

Ce serait vraiment bien de pouvoir faire cette extraction avec une seule exécution de cpio plutôt que de devoir boucler et extraire un file à la fois. Je suis sûr que c'est juste un problème avec la façon dont je fournis ces valeurs à cpio, mais pour la vie de moi je ne peux pas comprendre pourquoi.

Probablement pas pertinent, mais juste pour l'exhaustivité: c'est sur CentOS 7.2, en utilisant GNU cpio 2.11

cpio a une option -E ( --pattern-file ), qui vous permet de lire la list des noms de files à partir d'un file au lieu de (ou aussi bien que) en fournissant les noms de files sur la command line. Par exemple:

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

cpio également -F pour spécifier un nom d'archive (au lieu d'utiliser stdin / stdout). -I et -O sont similaires mais fonctionnent à la place de stdin ou stdout respectivement.

Par exemple, vous pouvez spécifier l'archive avec -F et fournir la list des files sur stdin:

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

ou utiliser les deux -E et -F

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

BTW, avec de nombreux programmes GNU (y compris cpio , les pages de man sont presque inutiles, mais elles sont bien documentées dans les files .info. vous devrez donc les installer ainsi qu'un lecteur d'informations (comme GNU info ou pinfo )

Quoi qu'il en soit, voici quelques extraits pertinents des pages info cpio :

-E FILE , --pattern-file=FILE

Lisez des templates supplémentaires en spécifiant les noms de files à extraire ou à listr à partir de FICHIER. Les lignes de FILE sont traitées comme si elles avaient été des arguments non-option à cpio. Cette option est utilisée en mode copy,

et

-F ARCHIVE , --file=ARCHIVE

Archiver le nom de file à utiliser à la place de l'input ou de la sortie standard. Pour utiliser un lecteur de bande sur une autre machine en tant HOSTNAME: , utilisez un nom de file qui commence par HOSTNAME: :, où HOSTNAME est le nom ou l'adresse IP de la machine. Le nom d'hôte peut être précédé d'un nom d'user et d'un @ pour accéder au lecteur de bande distant en tant qu'user, si vous en avez l'autorisation (généralement une input dans ~/.rhosts file ~/.rhosts user).

Les espaces dans les noms de files peuvent être difficiles, mais je pense que cela pourrait aider.

Au lieu de traiter vos files-à-extraire, essayez de le faire passer par xargs remplaçant le caractère NULL par EOL.

Quelque chose comme

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

devrait faire l'affaire.