Sono alle prese con un problema apparentemente banale ma da cui non riesco a uscire. Un sistema automatico genera una serie (numerosa) di directory e sottodirectory, ad esempio:

/home/chicco/ * / * /

ogni sottodirectory contiene evidentemente dei files. E' possibile dire con riga di comando al sistema di copiare ogni file di sottodirectory nella rispettiva directory superiore? (Insomma copiare ogni file contenuto in /home/chicco/ * / * / dentro a /home/chicco/ * / senza specificare il nome del percorso di partenza e di arrivo)

chiesto 08 Gen '15, 23:35

piccolo%20principiante's gravatar image

piccolo prin...
157132027

Sì, basta dare

cp /home/chicco/cartella/sottocartella/* /home/chicco/cartella/

EDIT: quello che avevo scritto prima non aveva senso :)

(09 Gen '15, 00:19) dadexix86 ♦♦ dadexix86's gravatar image

C'è da dire che come suggerisce @dadexix86, il comando cp copia i files da una cartella ad un'altra, lasciando la cartella d'origine inalterata, con tutti i files copiati nelle stesse condizioni in cui erano prima della copia, occupando solo più spazio
Se invece si volesse spostarli da una cartella ad un'altra, il comando cp andrebbe sostituito con il comando mv.
Però prima di spostarli bisogna fare attenzione al fatto che se questi files dovessero servire ad altri programmi, che per funzionare li cercano nella directory d'origine, non trovandoli potrebbero non funzionare correttamente.

(09 Gen '15, 07:39) enzoge enzoge's gravatar image

Il punto è che le cartelle sono numerose e le sottocartelle ancor più, e volevo compilare uno script che mi evitasse la scocciatura di dover specificare il nome di ogni cartella e sottocartella (che peraltro nel mio caso hanno nomi alfanumerici casuali). cp /home/chicco/ * / * /* /home/chicco/ * / * mi sembrava "onesto", ma la shell mi restituisce un errore di "redirezione ambigua" Per ora grazie ad entrambi, proverò la risposta di @enzotib

(09 Gen '15, 22:39) piccolo prin... piccolo%20principiante's gravatar image

Se ho capito bene, e se hai una struttura del tipo:

/base
/base/dir1
/base/dir1/subdir1
/base/dir1/subdir1/file1
/base/dir1/subdir1/file2
/base/dir1/subdir2
/base/dir1/subdir2/file3
/base/dir1/subdir2/file4
/base/dir2
/base/dir2/subdir3
/base/dir2/subdir3/file5
/base/dir2/subdir3/file6
/base/dir2/subdir4
/base/dir2/subdir4/file7
/base/dir2/subdir4/file8

allora puoi fare qualcosa del tipo (uso mv, che sposta, ma se vuoi effettivamente avere due copie di ogni file allora dovresti usare cp, che copia)

cd "/base"
for f in */*; do
    mv "$f"/* "${f%%/*}"
done

in modo da avere alla fine

/base
/base/dir1
/base/dir1/file1
/base/dir1/file2
/base/dir1/file3
/base/dir1/file4
/base/dir1/subdir1
/base/dir1/subdir2
/base/dir2
/base/dir2/file5
/base/dir2/file6
/base/dir2/file7
/base/dir2/file8
/base/dir2/subdir3
/base/dir2/subdir4

però attenzione, perché se per esempio hai un file con lo stesso nome in due subdir della stessa dir, per esempio

/base/dir1/subdir1/file1
/base/dir1/subdir2/file1

nello spostamento dovrebbero venire a trovarsi entrambi in /base/dir1, per cui il secondo che sposti sovrascriverà il primo.

Infine, per cancellare tutte le subdir vuote che ti restano, puoi fare

find . -type d -empty -delete
coll. permanente

ha risposto 09 Gen '15, 07:40

enzotib's gravatar image

enzotib ♦♦
14.0k112186

modificato 09 Gen '15, 07:41

@enzotib: mi complimento per la risposta.
Una domanda: quanto suggerito funziona anche in caso di files o directory nascoste?

(09 Gen '15, 08:05) enzoge enzoge's gravatar image

@ilgallinetta: no, affinché gli * che compaiono nel comando tengano conto anche dei file nascosti è necessario attivare l'opzione dotglob di bash con il comando

shopt -s dotglob

Per non avere in seguito sorprese, ricordarsi subito di rimettere le cose a posto con

shopt -u dotglob

(per aiutare la memoria, s ed u stanno per set e unset).

(09 Gen '15, 08:12) enzotib ♦♦ enzotib's gravatar image

@enzotib: ti ringrazio per il chiarimento.
Per cui, se ho capito bene, il comando

shopt -s dotglob

per evitare sorprese con files contenuti in cartelle nascoste,andrebbe impostato per primo.
Mentre il comando

shopt -u dotglob

sarebbe l'ultimo, dopo la cancellazione.

(09 Gen '15, 08:29) enzoge enzoge's gravatar image

Sì, proprio così. C'è da puntualizzare che questi comandi sono limitati a bash, quindi funzionano da linea di comando e con script eseguiti con bash. Se eseguiamo uno script con sh invece non c'è un modo semplice per gestire i file nascosti.

(09 Gen '15, 08:59) enzotib ♦♦ enzotib's gravatar image

@enzotib: ti ringrazio per i chiarimenti, che vista la ruggine della mia memoria fanno molto comodo.
Mi sembra però giusto ribadire a @piccolo prin... che nel caso questi files venissero usati da altri programmi, deve assicurarsi che possano poi trovarli.

(09 Gen '15, 09:10) enzoge enzoge's gravatar image

Grazie a tutti dell'interessamento e dell'aiuto. I files in questione fortunatamente vengono usati solo dallo script che sto costruendo. Provo quanto prima la risposta di @enzotib, anche se sono già sicuro che sarà - come al solito - efficace ;)

(09 Gen '15, 22:46) piccolo prin... piccolo%20principiante's gravatar image

@enzotib non conviene mettere degli apici qui

for f in "*/*"; do

nel caso le directory abbiano dei nomi con spazi?

(10 Gen '15, 11:13) dadexix86 ♦♦ dadexix86's gravatar image

@dadexix86: assolutamente no, altrimenti il carattere "*" non viene interpretato come dovrebbe. Inoltre in questa sintassi gli spazi vengono interpretati correttamente.
Esempio

cd
mkdir appo
cd appo
touch "aaa"
touch "b b"
for f in *; do
    echo "-- $f --"
done

l'output è

-- aaa --
-- b b --
(10 Gen '15, 11:18) enzotib ♦♦ enzotib's gravatar image

Come al solito, grazie :)

(10 Gen '15, 11:38) dadexix86 ♦♦ dadexix86's gravatar image
La tua risposta
abilita/disabilita anteprima

Segui questa domanda

Via email:

Una volta eseguito l'accesso potrai iscriverti a tutti gli aggiornamenti qui

Via RSS:

Risposte

Risposte e commenti

Basi di markdown

  • *corsivo* o __corsivo__
  • **grassetto** o __grassetto__
  • collegamento:[testo](http://url.com/ "titolo")
  • immagine?![alt testo](/path/img.jpg "titolo")
  • elenco numerato: 1. Foo 2. Bar
  • per aggiungere un'interruzione di riga, aggiungi due spazi a fine riga e premi «Invio»
  • è supportato anche semplice HTML

Tag:

×93
×7

domanda posta: 08 Gen '15, 23:35

domanda visualizzata: 1,179 volte

ultimo aggiornamento: 10 Gen '15, 11:38

Chiedi è un servizio di supporto gestito da Ubuntu-it. Contattaci!

powered by OSQAPostgreSQL database
Ubuntu e Canonical sono marchi registrati da Canonical Ltd.