
Angenommen, ich mache Folgendes:
tar cvf allfiles.tar $(<mylist.txt)
Undmeineliste.txtenthält Folgendes:
/tmp/lib1
/tmp/path2/lib2
/path3/lib3
Wie tarnt man die Dateien, so dass das Tarball nur
lib1
lib2
lib3
ohne jegliche Verzeichnisstruktur?
Normalerweise wird die Verwendung -C
von Optionen empfohlen (--directory
Referenz,Referenz), aber es gibt mehrere Verzeichnisse, also funktioniert das nicht. Außerdem --xform
sieht es so aus, als ob es ein festes Muster erfordert (Referenz), die wir nicht haben.
Antwort1
Das --xform
Argument akzeptiert eine beliebige Anzahl von sed
Ersatzausdrücken, die sehr leistungsfähig sind. Verwenden Sie in Ihrem Fall ein Muster, das bis zum letzten auf alles zutrifft /
, und ersetzen Sie es durch nichts:
tar cvf allfiles.tar --xform='s|.*/||' $(<mylist.txt)
Hinzufügen, --show-transformed-names
um die neuen Namen anzuzeigen.
Beachten Sie, dass diese Ersetzung für alle Dateinamen gilt, nicht nur für die in der Befehlszeile angegebenen. Wenn Sie also beispielsweise eine Datei haben /a/b/c
und Ihre Liste nur angibt /a
, ist der endgültige Dateiname nur c
und nicht b/c
. Sie können immer expliziter sein und eine genaue Liste der Ersetzungen angeben, z. B. in Ihrem Fall
--xform='s|^tmp/path2/||;s|^tmp/||;s|^path3/||'
Beachten Sie, dass der Anfangsbuchstabe /
von tar entfernt wird (es sei denn, Sie verwenden -P
), sodass er in den obigen Ausdrücken fehlt. Außerdem muss die Liste der Verzeichnisse sortiert werden, sodass die längste Übereinstimmung zuerst gefunden wird, sonst wird tmp/path2/
keine Übereinstimmung gefunden, da tmp/
sie bereits entfernt wurde. Sie können die Erstellung dieser Liste jedoch automatisieren, z. B.:
--xform="$(sed <mylist.txt 's|[^/]*$||; s|^/||; s:.*:s|^&||;:' | sort | tr -d '\n')"
Antwort2
Mit GNU tar
können Sie es -C
ab sofort verwenden, wann und so oft Sie möchten.
$ 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