PDA

Visualizza la versione completa : due domande su uno script bash


Sergej_D
10-07-2005, 18:56
Salve.
Scopiazzando qua e l, visto che capisco molto poco di bash, ho fatto questo piccolo script per sostituire strighe di caratteri in file:


for i in *; do mv "$i" `echo $i | tr -s '' 'a'`; done

1) se eseguo questo comando e lui non trova stringhe da sostituire mi restituisce un errore "mv: `prova.txt' e `prova.txt' sono lo stesso file". E cos per ogni file o directory in cui non ci sono caratteri da sostituire.
Come ovviare a questo comportamento?

2) vorrei che il comando sia valido non solo per i file e le cartelle presenti, ma che sia ricorsivo.
Come fare??

Grazie,
Sergej

Ilmalcom
10-07-2005, 19:04
1. Redirigi lo standard error su /dev/null appendendo al comando la seguente espressione:

2>/dev/null
Esempio

mv prova.txt nuovo.txt 2>/dev/null
2. Per farlo ricorsivo ci sono vari modi, forse la soluzione pi semplice per le tue esigenze prima lanciare il comando che hai scritto e poi, se non vi sono molti livelli di annidamento, ricorrere a forme del tipo

for i in */*; do mv "$i" `echo $i | tr -s '' 'a'`; done
Comunque c' ben pi di una soluzione, per esempio potresti sfruttare ls -R

for i in `ls -R`; do mv "$i" `echo $i | tr -s '' 'a'`; done
Potrebbero per verificarsi dei problemini con nomi di files particolari, vedi tu per cosa optare.

cacao74
10-07-2005, 19:18
Considera anche l'opzione '--force' del comando 'mv'.

man mv

ciao

Kamui
10-07-2005, 21:04
Se pu esserti utile, con questo comando ottieni il numero di livelli dell'albero (devi darlo tutto su una riga sola).



max=0; ls -R . | egrep ^'./' | while read riga; do zac=`echo $riga | sed -e "s/\///g"`;
let n=${#riga}-${#zac}; if [[ "$n" -gt "$max" ]]; then max=$n; echo $max; fi; done;

L'ultimo numero che ti esce sar quindi anche il numero di slash che dovrai mettere nel for per raggiungere l'ultimo livello.
Ad esempio se ti esce "3" come ultimo numero, il comando ricorsivo sar:



for i in */*/*/*; do mv "$i" `echo $i | tr -s '' 'a'`; done

Cos modifichi i file nell'ultimo livello di directory.
Poi ridai il comando togliendo uno slash, e cos via...

A te automatizzare tutto.

:incupito:

stai_tranquillo
11-07-2005, 12:20
perch invece di ammazzarti con mv non usi rename?

$ rename "" "a" *


:fagiano:

Sergej_D
11-07-2005, 12:53
A me servirebbe eseguire questo operazione molte volte, per cui pensavo di fare un script di questo tipo:


#!/bin/sh

# per per eliminare caratteri:

for i in *; do mv "$i" `echo $i | tr -d '"'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '''`; done 2>/dev/null


E cos molte volte.
Per, se faccio cos, fa casino, sostituisce cose che non deve sostituire... (sono almeno 25 righe cos).
Come dovrei fare per "concatenare" tutte le sostituzioni, magari in un unico ciclo di for?

Oppure,lasciando 25 righe cos, come devo fare per farlo funzionare decentemente?

Ho inserito una riga per ogni carattere da sostituire, e, per esempio, se ho un file "arriv.txt" ed eseguo lo script, mi diventa "arrivao.txt"...
Mentre se eseguo "separatamente" la riga per sostituire il carattere "" funziona bene.

Grazie,
Sergej

cacao74
11-07-2005, 13:09
cacao74@winnie:~/tmp$ echo cc | tr -t '' 'aeeiou'
cacao

ciao

Sergej_D
11-07-2005, 18:59
Dunque, c' un problema.
Se io ho un file r.txt ed eseguo il seguente comando da shell:


sergej[Prova]$ for i in *; do mv "$i" `echo $i | tr -s '' 'i'`; done 2>/dev/null

il file viene rinominato in ir.txt.

Se invece eseguo lo script completo, mi trasforma il file in eir.txt.

Ecco il codice completo:


#!/bin/sh

# per per eliminare caratteri:

for i in *; do mv "$i" `echo $i | tr -d '"'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '''`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '('`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d ')'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '{'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '}'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '\'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '?'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '&'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '='`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '~'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '!'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '%'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '<'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '>'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '*'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '&'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '&'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -d '&'`; done 2>/dev/null

# script per sostituire i caratteri:

for i in *; do mv "$i" `echo $i | tr -s '' 'a'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -s '' 'e'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -s '' 'e'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -s '' 'i'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -s '' 'o'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -s '' 'u'`; done 2>/dev/null
for i in *; do mv "$i" `echo $i | tr -s ' ' '_'`; done 2>/dev/null


Dove l'errore?

Sergej

Ilmalcom
12-07-2005, 11:12
Originariamente inviato da cacao74
cacao74@winnie:~/tmp$ echo cc | tr -t '' 'aeeiou'
cacao

ciao
La soluzione qui postata dovrebbe fare al caso tuo, sostituisci tutte quelle righe con il comando singolo e vedi se funziona. Comunque quei 2>/dev/null vanno messi dopo il tr e prima del punto e virgola, non dopo il done... Dovrebbe funzionare anche come hai fatto tu, ma a livello logico scorretto.

gianiaz
12-07-2005, 14:35
e se avessi 2 files cosi:


ncora
ancra


Tieni presente anche questo caso.

Forse il caso di usare un linguaggio di scripting tipo perl o python...

ciao

Loading