Voglio rinominare tutti i file contenuti in una cartella secondo i nomi contenuti in un file di testo.
I file nella cartella sono numeri (1 2 3 etc), i file nel testo anche (per evidenza ho messo (a b c etc).
Pensavo ad una cosa in bash con uno schema del tipo
for i in *
do
j=roba
mv $i $j
done
Per avere j volevo incastrare al posto di "roba" qualcosa come:
for k in $(cat testo.txt)
do
echo $k
done
beh ma allora non serve usare mv, conviene usare direttamente cp
potresti farti una variabile che contenga il testo del file, ogni campo separato da uno spazio, poi con awk prendi ogni elemento dentro un for
una roba del tipo
lista_nomi=$(cat file) #conterrà i nomi messi in un'unica riga, se non ricordo male)
for i in `ls -1 ./orig`; do
dest=$(echo $lista_nomi | awk '{print $i}')
cp i ./spostati/$dest
done
questo funziona se i file di origine hanno nomi esattamente del tipo 1 2 3 ecc
altrimenti bisogna lavorare su awk in modo da ottenere l'indice relativo del file rispetto al totale
cp: target `c` is not a directory
cp: target `c` is not a directory
cp: target `c` is not a directory
[gen@m4p ori]$ ls
1 2 3 nomi_fin py.py
[gen@m4p ori]$ python py.py
Renaming 1 -> a
Renaming 2 -> b
Renaming 3 -> c
[gen@m4p ori]$ cat py.py
import os
newNames = [x for x in open('nomi_fin', 'r').read().split('\n') if x != '']
curNames = [int(x) for x in os.listdir('./') if x not in ['', 'py.py', 'nomi_fin']]
curNames.sort()
if len(newNames) != len(curNames):
print('Length mismatch, something is wrong, ABORT ABORT ABORT')
for i in curNames:
print('Renaming {} -> {}'.format(i, newNames[i - 1]))
os.rename(str(i), newNames[i - 1])
[gen@m4p ori]$ cat nomi_fin
a
b
c
La struttura della cartella dev'essere ESATTAMENTE come questa, cioè:
1. ogni numero dev'essere consecutivo. Se non è così, lo script va cambiato (semplice ma mi scocciava, in caso lo cambio)
2. I file devono iniziare da 1 e non da 0. Se non è così, lo script va cambiato
3. il file python si deve chiamare py.py e deve stare nella cartella con i file da rinominare, la lista si deve chiamare nomi_fin e deve stare nella stessa cartella.
Lascia fare il codice a me. Ora supporta anche i nomi/numeri non consecutivi.
Codice:
import os, sys
newNames = [x for x in open('nomi_fin', 'r').read().split('\n') if x != '']
curNames = [int(x) for x in os.listdir('./') if x not in ['', 'py.py', 'nomi_fin']]
curNames.sort()
if len(newNames) != len(curNames):
print('Length mismatch, something is wrong, ABORT ABORT ABORT')
sys.exit(1)
for j in range(len(curNames)):
i = curNames[j]
print('Renaming {} -> {}'.format(i, newNames[j]))
os.rename(str(i), newNames[j])
È un quick hack, è nei quick hack si mette il minimo indispensabile al funzionamento. Se ci sono altri requisiti me li devi dire, così ce li metto. :asd:
#!/bin/bash
IFS='
' #separatore per gli elementi dell'array: a capo
#parametri#
ORIGINAL=./originali #percorso dei file da copiare
DESTINATION=./rinominati #percorso di destinazione
LIST=./lista #nome file che contiene la lista di nomi
array=($(ls -1 $ORIGINAL))
len=${#array[*]}
i=0
while [ $i -lt $len ]; do
row=$((i+1))'p' #calcolo la riga del file
name=$(sed -n "$row" < $LIST) #ricavo il nome dal file
cp $ORIGINAL/${array[$i]} $DESTINATION/"$name" #copio col nuovo nome
let i++
done
echo "done!"
testato e funziona.
i file devono essere del tipo 01 02 ecc, perchè ls li ordina in quel modo. altrimenti ti ritrovi 1 10 11 ... 2 20 .. ecc. scegli tu come preferisci. i nomi devono essere scritti in un file, un nome per riga, e possono anche contenere spazi. tutti i parametri sono all'inizio dello script.
non fa controllo d'errore, e nella cartella di origine devono esserci SOLO i file da copiare. nel caso si può fare un po' di codice in più di controllo, se serve
probabilmente c'è un modo per ordinare come ti pare :asd:
ps: aggiunto un controllo, ora nella cartella degli originali possono esserci anche cartelle, vengono ignorate.
#!/bin/bash
IFS='
' #separatore per gli elementi dell'array: a capo
#parametri#
ORIGINAL=./originali #percorso dei file da copiare
DESTINATION=./rinominati #percorso di destinazione
LIST=./lista #nome file che contiene la lista di nomi
array=($(ls -1p $ORIGINAL | grep "[^/]$"))
len=${#array[*]}
i=0
while [ $i -lt $len ]; do
row=$((i+1))'p' #calcolo la riga del file
name=$(sed -n "$row" < $LIST) #ricavo il nome dal file
cp $ORIGINAL/${array[$i]} $DESTINATION/"$name" #copio col nuovo nome
let i++
done
echo "done!"
fac iea, trovato:
-v natural sort of (version) numbers within text
#!/bin/bash
IFS='
' #separatore per gli elementi dell'array: a capo
#parametri#
ORIGINAL=./originali #percorso dei file da copiare
DESTINATION=./rinominati #percorso di destinazione
LIST=./lista #nome file che contiene la lista di nomi
array=($(ls -1pv $ORIGINAL | grep "[^/]$"))
len=${#array[*]}
i=0
while [ $i -lt $len ]; do
row=$((i+1))'p' #calcolo la riga del file
name=$(sed -n "$row" < $LIST) #ricavo il nome dal file
cp $ORIGINAL/${array[$i]} $DESTINATION/"$name" #copio col nuovo nome
let i++
done
echo "done!"
ora ordina i file anche se sono scritti 1 2 3 4 5 6 7 8 9 10 ecc, come ci si aspetterebbe.
a che minchia serve rinominare le cartelle? non è qualcosa che ha richiesto buntolo. e comunque, posso benissimo editare il codice in modo che rinomini anche quelle :P
python può pupparmela :drd: