[Risolto] Rinominare più file usando una stringa interna al file

Saluti a tutti,
ogni mese devo creare una serie di file da inviare alla banca per il pagamento telematico degli F24 dei clienti.

Il problema, il programma mi crea il file quasi correttamente ma i nomi dei clienti nel DB del programma sono scritti normalmente con l’iniziale maiuscola ed il resto minuscolo, il codice fiscale tutto in maiuscolo, quando il programma della banca fa la verifica sui dati anagrafici ed il C.F. si arrabbia perché Cognome e Nome non compaiono (nel C.F.) come CgnNmo ma come CGNNMO (lo so è un’assurdità).

Per ovviare sto scrivendomi un file batch che converte i file in tutte maiuscole e già che ci sono dargli il nome che la banca estrae dal file (in modo da essere allineati.

Sono riuscito a fare la prima parte$ for i in `ls *`; do cat $i|tr ':lower:]' ':upper:]'>$i.maiuscole;done che legge il file lo converte in maiuscole e ne salva l’output con il nome originale seguito dal suffisso “.maiuscole”.

Ho trovato pure il modo di isolare la stringa che dovrebbe diventare il nome reale del file $ for nome in `ls *`; do cut -b 9-36 $nome|head -n1;done

Quello che non riesco a fare è di integrare le due parti in modo da convertire direttamente i file e salvarli con il loro nome “$nome” anzichè fare un secondo passaggio a mano con il copia/incolla.

P.S. cercando in rete ho notato che spesso i nomi delle variabili sono scritti in maiuscolo, è una prassi consolidata o sono preferenze personali?

Grazie a tutti

Edit:
Ho dovuto modificare il titolo altrimenti non entrava il [Risolto]

La prassi che conosco dice:

  • costanti in maiuscolo (PI=3.14…)
  • i nomi devono essere parlanti (raggio,diametro)
for cf in `ls`
do
	nome=`head -n1 $cf | cut -b 9-36 | tr ':lower:]' ':upper:]'`
	tr ':lower:]' ':upper:]' $cf > $nome
done

R.

Se paghi in monetine da 1¢ o con casse di birra ti tolgo la Zanicchi. :stuck_out_tongue:

Puoi farci vedere un frammento di file cambiando magari i nomi? credo che quel cut magari si possa migliorare. Tra l’altro, non è necessario usare ls *, basta il semplice asterisco.

Grazie a tutti, scusate il ritardo ma questa mattina seguivo un corso sulla fatturazione alla pubblica amministrazione (l’UCAS è sempre in agguato :slight_smile: ).

@romulus
Ho provato il tuo script, ma mi da questo errore

tr: extra operand `M05696AC' Try `tr --help' for more information.
e produce solo file da 0 byte

@ frafra
la prima riga, quella dove c’è la stringa, è questa (il primo è uno spazio)

F4XXXXX01005160714F2420140716164859 2$05696 E ^^^^^^^^^^^^^^^^^^^^^^^^^^^^la parte che dovrebbe diventare il nome è quella sottolineata dai ‘^’.
Se serve anche il resto del file a coprire nomi, codici fiscali, ecc… ci vuole poco ma considerato che il forum è pubblico meno posto meglio è.

Forse si può migliorare (frafra docet), ma lo script di romulus modificato così funziona bene$ for cf in *; do nome=`head -n1 $cf | cut -b 9-36`; cat $cf|tr ':lower:]' ':upper:]' > $nome; done
in pratica ho tolto la trasformazione in maiuscole di $nome ed ho modificato la seconda parte con ‘cat $cf | tr ecc…’

Edit:
Se non ci sono miglioramenti da apportare io metterei pure il [Risolto]

dimentico sempre che funziona:

tr  ... < input > output

e non

tr ... input output

e questo spiega perché di solito si usa

cmd | tr > output
cmd1 | tr | cmd2

Suggermento:

se puoi evita sempre cose tipo

for file in * ...
for file in `ls *`
for file in `ls *.ext`

puoi incorrere nell’errore di troppi argomenti; tu sai cosa stai facendo,
ma lo fai con il lavoro svolto da altri, un errore banale e potresti trovarti
con le directory piene, e allora…
meglio

for file in `ls` ...
for file in `ls | egrep '\.ext$'` ...

R.

(Loop con command substitutions del tipo for file in `ls *` e varianti sarebbero sempre da evitare, ls è innecessario ed è foriero di http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29)

Per cui essendo il nome originale del file composto da “M”+“ABI”+“sigla utente” (in parole povere uno dei nomi è M01005AC) dove il prefisso “M” è fisso, la mia sigla utente è “AC” sarebbe meglio un for 'ls M*AC' o un for 'ls M?????AC' ?

(considerando che sono solo io a gestire questi file quindi la sigla non cambia).

ahem forse ti sono scappati i post #3 e #7 :hehe:
Abbandona ls, l’output di ls non dovrebbe essere mai analizzato per un loop; tra una wildcard generica e una specifica, è meglio quella specifica. Senza find, una soluzione potrebbe essere

$ for cf in M[0-9][0-9][0-9][0-9][0-9]AC; do  -e $cf ]] || continue; nome=$(head -n1 "$cf" | cut -b 9-36); cat "$cf"|tr ':lower:]' ':upper:]' > "$nome"; done

Per cui meglio le espressiono regolari che i jolly, poi mi informo meglio sulla parte -e $cf ]] || continue

Grazie

Quel passaggio semplicemente verifica che $cf sia un file; se non lo è si passa al successiva iterazione del loop. Se non ci sono file corrispondenti all’espressione richiamata $cf assume il valore dell’espressione in sè, e tutta l’iterazione viene eseguita. Aggiungendo questo passaggio invece si esce subito dal loop, in tale scenario. E’ l’equivalente do -e $cf ]] && comando; done, con la differenza che && permette di filtrare l’esecuzione del solo comando che va a precedere.

Messo in “produzione”, il lavoro che prima mi impegnava 1/2 mattinata fatto in 5 minuti.

Grazie a tutti