Come faccio a Tar A directory di file e cartelle senza includere la directory stessa?

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

  •  06-09-2019
  •  | 
  •  

Domanda

Io di solito faccio:

tar -czvf my_directory.tar.gz my_directory

Che cosa succede se voglio solo includere tutto (inclusi i file di sistema nascoste) in my_directory, ma non la directory stessa? Non voglio:

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

Voglio

my_file
my_file
my_file
È stato utile?

Soluzione

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

dovrebbe fare il lavoro in una sola riga. Funziona bene per i file nascosti pure. "*" Non espandere i file nascosti di espansione nome del percorso, almeno in bash. Di seguito è riportato il mio esperimento:

$ 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

Altri suggerimenti

Con l'interruttore -C di catrame:

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

Il -C my_directory dice a tar di cambiare la directory corrente my_directory, e poi . significa "aggiungere tutta la directory corrente" (inclusi i file nascosti e le sotto-directory).

Assicurati di fare -C my_directory prima di fare . altrimenti otterrai i file nella directory corrente.

È anche possibile creare archivi come al solito e estrarlo con:

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

Date un'occhiata al --transform / --xform, ti dà l'opportunità di massaggiare il nome del file come il file viene aggiunto all'archivio:

% 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

Transform espressione è simile a quella di sed, e possiamo usare separatori diversi / (, nell'esempio precedente).
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 -

Con alcune condizioni (archiviare solo i file, dirs e collegamenti simbolici):

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

Spiegazione

Il include seguito purtroppo ./ directory padre in archivio:

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

È possibile spostare tutti i file su quella directory utilizzando l'opzione di configurazione --transform, ma questo non sbarazzarsi della directory . stesso. Diventa sempre più difficile da domare il comando.

Si potrebbe utilizzare $(find ...) per aggiungere un elenco di file al comando (come in magnus' risposta ), ma che potenzialmente errore di cause di un "elenco di file troppo lungo". Il modo migliore è quello di combinarlo con l'opzione -T di catrame, in questo modo:

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

In sostanza ciò che fa è la lista di tutti i file (-type f), link (-type l) e le sottodirectory (-type d) sotto la directory, fare tutti i nomi dei file relativi utilizzando -printf "%P\n" e quindi passare che per il comando tar (ci vogliono i nomi dei file da STDIN utilizzando -T -). L'opzione -C è necessario in modo tar sa dove si trovano i file con nomi relativi. La bandiera --no-recursion è così che tar non recurse in cartelle viene detto di archivio (che causa i file duplicati).

Se avete bisogno di fare qualcosa di speciale con i nomi dei file (filtraggio, seguendo i link simbolici, ecc), il comando find è abbastanza potente, e si può testare rimuovendo solo la parte tar del comando di cui sopra:

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

Per esempio, se si desidera filtrare i file PDF, aggiungere ! -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 trovare

Il comando utilizza printf (disponibile in GNU find) che racconta find di stampare i risultati con i percorsi relativi. Tuttavia, se non si dispone di GNU find, questo funziona per rendere i percorsi relativi (rimuove i genitori con 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 -

Questa risposta dovrebbe funzionare nella maggior parte delle situazioni. Si noti tuttavia come i nomi dei file sono memorizzati nel file tar, come, ad esempio, ./file1 piuttosto che solo file1. Ho trovato che questo ha causato problemi quando si utilizza questo metodo per manipolare i tarball usate come file dei pacchetti in BuildRoot .

Una soluzione è quella di utilizzare alcune gocce Bash per elencare tutti i file ad eccezione di .. in questo modo:

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

Questo è un trucco che ho imparato da questa risposta .

Ora tar restituisce un errore se non ci sono file corrispondenti ..?* o .[^.]*, ma sarà ancora funzionare. Se l'errore è un problema (che si sta verificando per il successo in uno script), questo funziona:

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

Anche se ora siamo scherzi con opzioni di shell, potremmo decidere che è più ordinato di avere file nascosti * partita:

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

Questo potrebbe non funzionare in cui la shell globs * nella directory corrente, quindi in alternativa, utilizzare:

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 *

Se si tratta di un sistema Unix / Linux, e vi preoccupate per i file nascosti (che mancherà a *), è necessario fare:

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

Non so che cosa i file nascosti assomigliano sotto Windows.

proporrei la seguente funzione Bash (primo parametro è il percorso del dir, secondo argomento è il nome di base risultante archivio):

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"
}

È possibile eseguire in questo modo:

$ tar_dir_contents /path/to/some/dir my_archive

e genererà la my_archive.tar.gz dell'archivio all'interno di directory corrente. Funziona con elementi nascosti (. *) E con elementi con spazi nel loro nome.

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

Questo ha funzionato per me ed è includere tutti i file nascosti, senza mettere tutti i file in una directory principale denominata "" come in risposta di Tomoe :

Usa pax.

Pax è un pacchetto obsoleto, ma fa il lavoro perfettamente e in modo semplice.

pax -w > mydir.tar mydir

Il modo più semplice che ho trovato:

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=-
}

gestisce in modo sicuro i nomi di file con spazi o altri caratteri insoliti. Opzionalmente si può aggiungere un -name '*.sql' o un filtro simile al comando find per limitare i file inclusi.

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

Se la cartella è mytemp allora se si applica la sopra di esso sarà zip e rimuovere tutti i file nella cartella, ma lascia stare

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

Si può dare esclude modelli e anche specificare di non guardare in sottocartelle troppo

tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top