Wie tar ich ein Verzeichnis von Dateien und Ordnern, ohne das Verzeichnis einschließlich sich selbst?

StackOverflow https://stackoverflow.com/questions/939982

  •  06-09-2019
  •  | 
  •  

Frage

ich in der Regel tun:

tar -czvf my_directory.tar.gz my_directory

Was passiert, wenn ich will nur alles enthalten (einschließlich versteckte Systemdateien) in my_directory, aber nicht das Verzeichnis selbst? Ich will nicht:

my_directory
   --- my_file
   --- my_file
   --- my_file

Ich möchte:

my_file
my_file
my_file
War es hilfreich?

Lösung

cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd - 

sollte die Arbeit in einer Zeile tun. Es funktioniert gut für als auch versteckte Dateien. „*“ Nicht erweitert nicht versteckte Dateien durch Pfadnamen Expansion zumindest in bash. Unten ist mein Versuch:

$ mkdir my_directory
$ touch my_directory/file1
$ touch my_directory/file2
$ touch my_directory/.hiddenfile1
$ touch my_directory/.hiddenfile2
$ cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd ..
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
$ tar ztf my_dir.tgz
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2

Andere Tipps

den -C Schalter von Teer Verwendung:

tar -czvf my_directory.tar.gz -C my_directory .

Der -C my_directory tar sagt das aktuelle Verzeichnis zu ändern, my_directory und dann bedeutet . „fügen Sie den gesamten aktuellen Verzeichnis“ (einschließlich der versteckten Dateien und Unterverzeichnisse).

Stellen Sie sicher, Sie tun -C my_directory bevor Sie . tun oder sonst werden Sie die Dateien im aktuellen Verzeichnis.

Sie können auch erstellen Archiv wie gewohnt und entpacken Sie es mit:

tar --strip-components 1 -xvf my_directory.tar.gz

Hier finden Sie aktuelle --transform / --xform, es gibt Ihnen die Möglichkeit die Dateinamen zu massieren, wie die Datei in dem Archiv hinzugefügt wird:

% mkdir my_directory
% touch my_directory/file1
% touch my_directory/file2
% touch my_directory/.hiddenfile1
% touch my_directory/.hiddenfile2
% tar -v -c -f my_dir.tgz --xform='s,my_directory/,,' $(find my_directory -type f)
my_directory/file2
my_directory/.hiddenfile1
my_directory/.hiddenfile2
my_directory/file1
% tar -t -f my_dir.tgz 
file2
.hiddenfile1
.hiddenfile2
file1

Trans Ausdruck, dass der sed ähnlich ist, und wir können andere Trennzeichen verwenden als / (, im obigen Beispiel).
https://www.gnu.org/software/tar/manual/html_section /tar_52.html

TL; DR

find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Bei einigen Bedingungen (Archiv nur Dateien, Verzeichnissen und Symlinks):

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Erklärung

Die unten leider enthält ein übergeordnetes Verzeichnis ./ im Archiv:

tar -czf mydir.tgz -C /my/dir .

Sie können alle Dateien verschieben aus diesem Verzeichnis durch die --transform Konfigurationsoption verwenden, aber das bekommen nicht loswerden der . Verzeichnis selbst. Es wird immer schwieriger, den Befehl zu zähmen.

Sie könnten $(find ...) verwenden, um eine Dateiliste mit dem Befehl hinzufügen (wie in magnus' Antwort ), aber das potentiell Ursachen „Dateiliste zu lang“ Fehler ein. Der beste Weg ist es zu kombinieren mit tar -T Option, wie folgt aus:

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Im Grunde, was es tut, ist die Liste aller Dateien (-type f), Links (-type l) und Unterverzeichnisse (-type d) unter dem Verzeichnis, alle Dateinamen machen relativ -printf "%P\n" verwenden, und dann, dass mit dem Befehl tar übergeben (es dauert Dateinamen von STDIN mit -T -). Die -C Option wird benötigt, so Teer weiß, wo die Dateien mit relativen Namen befinden. Die --no-recursion Flagge ist so, dass tar Rekursion nicht in Ordnern ist es zum Archiv gesagt (was doppelte Dateien).

Wenn Sie etwas Besonderes mit Dateinamen tun (Filterung, symbolischen Links usw.), der find Befehl ist ziemlich mächtig, und Sie können es testen, indem Sie einfach den tar Teil des obigen Befehls zu entfernen:

$ find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore

Zum Beispiel, wenn Sie wollen PDF-Dateien filtern, fügen ! -name '*.pdf'

$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore

Non-GNU finden

Der Befehl verwendet printf (erhältlich in GNU find), die find erzählt seine Ergebnisse mit relativen Pfaden zu drucken. Wenn Sie jedoch nicht GNU find haben, funktioniert diese die Pfade relativ zu machen (entfernt Eltern mit sed):

find /my/dir/ -type f -o -type l -o -type d | sed s,^/my/dir/,, | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Diese Antwort sollte in den meisten Situationen. Beachten Sie jedoch, wie die Dateinamen in der TAR-Datei gespeichert werden, wie zum Beispiel ./file1 anstatt nur file1. Ich fand, dass diese Probleme verursacht, wenn mit dieser Methode tarballs als Paketdateien in BuildRoot .

Eine Lösung ist es, einige Bash Klackse zu verwenden, um alle Dateien mit Ausnahme .. wie diese aufzulisten:

tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *

Dies ist ein Trick, den ich von diese Antwort .

Jetzt tar einen Fehler zurück, wenn es keine entsprechenden Dateien ..?* oder .[^.]* sind, aber es wird immer noch funktionieren. Wenn der Fehler ein Problem ist (Sie in einem Skript für den Erfolg sind die Überprüfung), das funktioniert:

shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob

Auch wenn wir jetzt mit Shell-Optionen sind Messing, könnten wir entscheiden, dass es ordentlicheres ist * Spiel versteckte Dateien zu haben:

shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob

Dies könnte nicht arbeiten, wo Shell Klackse * im aktuellen Verzeichnis, so alternativ, zu verwenden:

shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
cd my_directory
tar zcvf ../my_directory.tar.gz *

Wenn es ein Unix / Linux-System ist, und Sie kümmern sich um versteckte Dateien (die mit * verfehlt wird), was Sie tun müssen:

cd my_directory
tar zcvf ../my_directory.tar.gz * .??*

Ich weiß nicht, was versteckte Dateien wie unter Windows aussehen.

würde ich die folgende Bash Funktion vorschlagen (erstes Argument ist der Pfad zu dem Verzeichnis, die zweite Argument ist der Basisname des resultierenden Archivs):

function tar_dir_contents ()
{
    local DIRPATH="$1"
    local TARARCH="$2.tar.gz"
    local ORGIFS="$IFS"
    IFS=$'\n'
    tar -C "$DIRPATH" -czf "$TARARCH" $( ls -a "$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
    IFS="$ORGIFS"
}

Sie können es auf diese Weise ausgeführt werden:

$ tar_dir_contents /path/to/some/dir my_archive

, und es wird das Archiv my_archive.tar.gz im aktuellen Verzeichnis erzeugen. Es arbeitet mit versteckten (. *) Elementen und mit Elementen mit Leerzeichen im Dateinamen.

cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..

Dies ist für mich gearbeitet und es ist alle versteckten Dateien enthalten, ohne dass alle Dateien in einem Stammverzeichnis zu setzen Namen „“ wie in Tomoe Antwort :

Mit pax.

Pax ist ein veraltetes Paket aber macht den Job perfekt und auf einfache Art und Weise.

pax -w > mydir.tar mydir

einfachste Weg, ich gefunden:

cd my_dir && tar -czvf ../my_dir.tar.gz *

# tar all files within and deeper in a given directory
# with no prefixes ( neither <directory>/ nor ./ )
# parameters: <source directory> <target archive file>
function tar_all_in_dir {
    { cd "$1" && find -type f -print0; } \
    | cut --zero-terminated --characters=3- \
    | tar --create --file="$2" --directory="$1" --null --files-from=-
}

Sicher Handhabung von Dateinamen mit Leerzeichen oder anderen Sonderzeichen. Optional können Sie einen -name '*.sql' oder ähnlichen Filter mit dem Befehl find in dem die Dateien beschränken enthielten.

 tar -cvzf  tarlearn.tar.gz --remove-files mytemp/*

Wenn der Ordner ist mytemp dann, wenn Sie gelten die oben wird es zip und alle Dateien in dem Ordner entfernen, aber es allein lassen

 tar -cvzf  tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*

Sie können ein Muster ausschließen und gibt auch nicht in Unterordner aussehen zu

tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top