Come organizzare i file in directory denominate di conseguenza dalla row di command sotto Linux

Ho una directory riempita di file diversi, denominati in modo diverso (cioè non nominati con un model specifico) e con estensioni diverse e voglio mettere ciascun file in una sottodirectory appena creata dopo each file; qual è il modo migliore per eseguire ciò dalla linea di command sotto Linux?
Questo mi sembra un po 'confuso, lasciathemes fare ed esempio: chiamiamo un file random nella directory ./filename.ext , vorrei metterlo in una sottodirectory denominata ./filename modo che in modo efficace il nuovo path sarà ./filename/filename.ext .

Ho fatto alcune prove con i seguenti passaggi:

  • Ho creato alcuni file di prova, da file-1.txt a file-9.txt , all'interno di una directory di test con for num in {1..9}; do touch file-$num.txt; done for num in {1..9}; do touch file-$num.txt; done
  • Ho creato una directory denominata dopo each nome di file con il for name in $(eval ls | cut -b 1-6); do mkdir $name; done for name in $(eval ls | cut -b 1-6); do mkdir $name; done
  • Ho spostato i file di origine nelle rispettive directory con il for name in $(eval ls | grep -e ".txt" | cut -b 1-6); do mv $name.txt $name/$name.txt; done for name in $(eval ls | grep -e ".txt" | cut -b 1-6); do mv $name.txt $name/$name.txt; done

Come si può vedere, questa soluzione funziona, ma il suo enorme inconveniente è che funziona proprio in questo caso, con file di quel file di file extact lungo e con quella particolare estensione. Se ho alcuni file con nomi e estensioni diversi, questo non sarebbe affatto utile. L'uso del command cut non è la soluzione ideale qui, suppongo, ma non ho trovato niente di meglio al momento.

Come bonus, sarebbe bello trovare un modo per creare automaticamente le subdir quando si sposta / rinominare i file senza wherer usare mkdir precedenza (quindi quando devo rinominare, non devo preoccuparmi di escludere i nuovi create directory); ma alla fine questo è un problema secondario.

Suppongo che la soluzione al tuo problema si chiami sostituzione dei parametri (guarda la descrizione dettagliata ). Dato un nome di un file nel filename del filename , riceverai la sua estensione usando ${filename##*.} E il nome con estensione w / o con ${filename%.*} .

Detto questo, potresti voler modificare il tuo for loop come:

 # for all (*) files in the current directory for i in *; do # -f checks if it is a file (skip directories) [ -f "$i" ] || continue # store the file name in filename filename=$(basename $i) # ext = the extension of the file (here we don't care, jfi) ext="${filename##*.}" # dir = the file name without its extension dir="${filename%.*}" # create the directory mkdir -p $dir # move the file in that directory mv $i $dir done 

Purtroppo, non ho ottenuto il punto del tuo task bonus , quindi rimarrà una sfida aperta … 🙂

Ecco un approccio con less scrip di shell, ma altri comandi.

  find -maxdepth 1 -type f > file-list 

Trova tutti i file nella directory corrente e salva questo elenco.

  grep -o '\./.*\.' file-list | sed s/\.$// > dir-list 

Filtra questa list per includere solo i nomi di file che hanno un punto da qualche parte. Rimuovi questo ultimo punto con sed, salvare questa list.

  mkdir $(<dir-list) 

Crea tutte le cartelle.

  sort dir-list > dir-list.s sort file-list > file-list.s 

Ciò è per allignare (per ordine elencato) i nomi dei file con i nomi delle cartelle>

  paste file-list dir-list 

Ciò sembrerà inesatto perché l' elenco dei file di file sarà qui. Nel mio caso c'era anche un file chiamato random . Eliminare questi nomi dall'elenco dei file.

  sed -E '/^\.\/(random|file-list)$/d' -i file-list sort file-list > file-list.s 

Esplora ancora una volta l'output del seguente command: incolla l'elenco file-list dir-list

Dovrebbe sembrare come questo:

  ./CCrtWW].GdH ./CCrtWW] ./c[ifzJlKnEYXO.wXF ./c[ifzJlKnEYXO ./FAEhz.u[A ./FAEhz ./FGMlrKcJHF.pHp ./FGMlrKcJHF ./HGxKPWZK.MpK ./HGxKPWZK ./JxwNrN.zoj ./JxwNrN 

Una volta che sembra giusto, fare uno script di shell fuori l'elenco e sun it:

  paste file-list dir-list | sed 's/^/mv -v /' | sh