[Risolto] [Bash] Spostare ricorsivamente file in una sottocartella

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
teomat
Prode Principiante
Messaggi: 76
Iscrizione: martedì 28 febbraio 2012, 13:33

[Risolto] [Bash] Spostare ricorsivamente file in una sottocartella

Messaggio da teomat »

Buongiorno a tutti,

lo so che esistono molto filoni simili, ma non ho trovato la soluzione al mio problema.
La situazione è la seguente; in una cartella-madre ho questa ramificazione

CartellaA
----N file PDF
----Sottocartella

Cartella B
----N file PDF
----Sottocartella

Le sottocartelle si chiamano sempre allo stesso modo; vorrei spostare ricorsivamente i file PDF nella "Sottocartella" relativa, che si trova allo stesso livello dei file pdf.
Idealmente questo sistema dovrebbe poter funzionare anche con CMDER sotto Windows.

Grazie in anticipo e a presto,
Matteo
Ultima modifica di teomat il martedì 8 febbraio 2022, 15:34, modificato 2 volte in totale.
Lucio C
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 371
Iscrizione: venerdì 10 dicembre 2021, 18:33
Desktop: fvwm
Distribuzione: (X)Ubuntu20@home; openSUSE42.3@work
Sesso: Maschile
Località: Paneropoli

Re: [Bash] Spostare ricorsivamente file in una sottocartella

Messaggio da Lucio C »

Cioe' partire da

Codice: Seleziona tutto

ls *
dirA:
due.pdf  Pippo/  tre.pdf  uno.pdf

dirB:
111.pdf  222.pdf  333.pdf  Pippo/
Basta dare (dal parente di dirA e dirB) i due comandi

Codice: Seleziona tutto

mv dirA/*pdf dirA/Pippo
mv dirB/*.pdf dirB/Pippo
et voila'

Codice: Seleziona tutto

ls */*
dirA/Pippo:
due.pdf  tre.pdf  uno.pdf

dirB/Pippo:
111.pdf  222.pdf  333.pdf
NB tutto cio' non ha niente di "ricorsivo"
The reasonable man adapts himself to the world: the unreasonable one persists in trying to adapt the world to himself. Therefore all progress depends on the unreasonable man. (G.B. Shaw)
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Bash] Spostare ricorsivamente file in una sottocartella

Messaggio da vaeVictis »

Come ti ha fatto notare @Lucio C la procedura ha poco o niente di ricorsivo.
Io procederei come segue, che è un modo un po' più generico rispetto allo spostamento a mano del contenuto di ogni singola cartella.

Creo la tua struttura in un directory Prova, con questi comandi

Codice: Seleziona tutto

$ mkdir -p Prova/Dir{A,B,C,D,E}/Sottocartella
$ touch Prova/Dir{A,B,C,D,E}/file{1,2,3,4,5,6,7,8}.pdf
dopodichè imposto due variabili e do il comando:

Codice: Seleziona tutto

$ motherDir=./Prova
$ destDir=Sottocartella
$ find "$motherDir" -mindepth 2 -maxdepth 2 -type f -iname "*pdf" | while read filePath; do fileName=$(basename "$filePath") && dirPath=$(dirname "$filePath" ) && mv "$filePath" "$dirPath"/"$destDir"/"$fileName" ; done
Al posto di motherDir puoi mettere il percorso assoluto della effettiva directory che contiene tutto, o il percorso relativo a partire da dove sei nel terminale quando lanci il comando.
Al posto di destDir puoi mettere il nome della tua directory in cui vuoi spostare tutto, che nel tuo esempio hai chiamato Sottocartella.

Spiegazione del comando:

Codice: Seleziona tutto

find "$motherDir" -mindepth 2 -maxdepth 2 -type f -iname "*pdf"
ti trova tutti i file con estensione pdf (senza distinzione tra maiuscole e minuscole, quindi pure PdF e via dicendo) contenuti nelle prime sottodirectory di motherDir.
Poi in pipe c'è questo ciclo while:

Codice: Seleziona tutto

while read filePath; do fileName=$(basename "$filePath") && dirPath=$(dirname "$filePath" ) && mv "$filePath" "$dirPath"/"$destDir"/"$fileName" ; done
quindi per ogni filePath con estensione pdf trovato, fa queste operazioni:
1) assegna a fileName il nome del file

Codice: Seleziona tutto

fileName=$(basename "$filePath")
quindi se ha trovato Pippo/Pluto/DirA/file_trovato.pdf fileName sarà uguale a file_trovato.pdf (e in questo caso morhetDir è ovviamente uguale a Pippo/Pluto)
2) assegna a dirPath il path della directory che contiene il file

Codice: Seleziona tutto

dirPath=$(dirname "$filePath" )
quindi con l'esempio di sopra dirPath sarà uguale a Pippo/Pluto/DirA/
3) con il comando

Codice: Seleziona tutto

mv "$filePath" "$dirPath"/"$destDir"/"$fileName"
sposta i file come richiesto, in quando la destinazione "$dirPath"/"$destDir"/"$fileName" è costruita in modo che, se, come nell'esempio fatto sopra, hai destDir uguale a "Sottocartella", sia uguale a Pippo/Pluto/DirA/Sottocartella/file_trovato.pdf

Se vuoi invece evitare la dipendenza da dirname e basename, puoi cambiare il ciclo while in

Codice: Seleziona tutto

while read filePath; do mv "$filePath" "${filePath%/*}"/"$destDir"/"${filePath##*/}"
In questo modo bash non chiama comandi esterni ma usa la manipolazione delle stringhe e se devi spostare un gran numero di file lo script è più veloce.
Queste due particolari manipolazioni delle stringhe funzionano così:
con

Codice: Seleziona tutto

$ filePath=./Cartella/SottoCartella/file.txt
avrai:

Codice: Seleziona tutto

$ echo "${filePath%/*}"
./Cartella/SottoCartella
e

Codice: Seleziona tutto

echo "${filePath##*/}"
file.txt
La prima è

Codice: Seleziona tutto

${string%substring}
che rimuove il più piccolo match di substring a partire dalla fine di string.
Quindi, come usata sopra, substring è uguale a /*
In questo modo ti leva tutto a partire da destra fino alla prima /, e quindi ti lascia la directory che contiene il file.

La seconda è

Codice: Seleziona tutto

${string##substring}
che rimuove il più lungo match di substring a partire dall'inizio della stringa.
Quindi, come usato sopra, substring è uguale a */
In questo modo ti leva tutto a partire da sinistra e fino all'ultimo /, lasciando quindi solo il nome del file.
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
teomat
Prode Principiante
Messaggi: 76
Iscrizione: martedì 28 febbraio 2012, 13:33

Re: [Bash] Spostare ricorsivamente file in una sottocartella

Messaggio da teomat »

Molte grazie, funziona tutto benissimo e grazie anche per la spiegazione particolareggiata.

A presto,
Matteo
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Bash] Spostare ricorsivamente file in una sottocartella

Messaggio da vaeVictis »

teomat ha scritto:
martedì 8 febbraio 2022, 14:56
Molte grazie, funziona tutto benissimo e grazie anche per la spiegazione particolareggiata.

A presto,
Matteo
Figurati.
Una sola osservazione. Nel titolo va scritto [Risolto], non "risolto-".
Ciao.
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
teomat
Prode Principiante
Messaggi: 76
Iscrizione: martedì 28 febbraio 2012, 13:33

Re: [Risolto] [Bash] Spostare ricorsivamente file in una sottocartella

Messaggio da teomat »

Fatto, grazie mille per l'osservazione!
M.F.
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 21 ospiti