Tar una lista de archivos sin su estructura de directorios

Tar una lista de archivos sin su estructura de directorios

Di que hago esto:

tar cvf allfiles.tar $(<mylist.txt)

ymilista.txtcontiene esto:

/tmp/lib1
/tmp/path2/lib2
/path3/lib3

Cómo tar los archivos para que el tarball contenga solo

lib1
lib2
lib3

¿Sin ninguna estructura de directorios?


Generalmente se recomiendan las -Copciones (--directoryárbitro,árbitro), pero hay varios directorios, por lo que esto no funciona. Además, --xformparece que requiere un patrón fijo (árbitro) que no tenemos.

Respuesta1

El --xformargumento toma cualquier número de sedexpresiones sustitutas, que son muy poderosas. En tu caso usa un patrón que coincida con todo hasta el último /y reemplázalo por nada:

tar cvf allfiles.tar --xform='s|.*/||' $(<mylist.txt)

Añadir --show-transformed-namespara ver los nuevos nombres.

Tenga en cuenta que esta sustitución se aplica a todos los nombres de archivos, no solo a los proporcionados en la línea de comando, por lo que, por ejemplo, si tiene un archivo /a/b/cy su lista solo especifica /a, entonces el nombre de archivo final es solo c, no b/c. Siempre puedes ser más explícito y proporcionar una lista exacta de sustituciones, por ejemplo, en tu caso.

--xform='s|^tmp/path2/||;s|^tmp/||;s|^path3/||'

/Tenga en cuenta que tar eliminará la inicial (a menos que use -P), por lo que falta en las expresiones anteriores. Además, la lista de directorios debe ordenarse de modo que la coincidencia más larga se realice primero; de lo contrario, tmp/path2/no coincidirá porque tmp/ya se eliminó. Pero puedes automatizar la creación de esta lista, por ejemplo:

--xform="$(sed <mylist.txt 's|[^/]*$||; s|^/||; s:.*:s|^&||;:' | sort | tr -d '\n')"

Respuesta2

Con GNU tar, puedes usarlo -Ccuando y con tanta frecuencia como quieras, con efecto inmediato.

$ tree
.
├── 1
│   └── aaa
├── 2
│   └── bbb
└── 3
    └── ccc



# Caveat: the directory change is always relative to directory tar is using *at
# that time*, so the following doesn't work:
$ tar -cf foo.tar -C 1 aaa -C 2 bbb -C 3 ccc  
tar: 2: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now

$ tar -cf foo.tar -C 1 aaa -C ../2 bbb -C ../3 ccc

$ tar tf foo.tar
aaa
bbb
ccc


# You can avoid the special case for the first directory by always specifying
# an absolute path:
$ tar -cf foo.tar -C $(pwd)/1 aaa -C $(pwd)/2 bbb -C $(pwd)/3 ccc



# Now let's create that automatically from your file:
$ cat mylist.txt
/tmp/1/aaa
/tmp/2/bbb
/tmp/3/ccc

$ while read -r line; do printf '-C %s %s ' $(dirname "$line") $(basename "$line") ; done < mylist.txt
-C /tmp/1 aaa -C /tmp/2 bbb -C /tmp/3 ccc 

# That looks about right. Let's use it in our tar command:
$ tar -cvf foo.tar $(while read -r line; do printf '-C %s %s ' $(dirname "$line") $(basename "$line") ; done < mylist.txt)
aaa
bbb
ccc

información relacionada