Pagina 1 di 2

Bash: xargs, variabili e spazi

Inviato: lun 9 giu 2008, 21:29
da anycolouryoulike
Sto provando a fare uno script per convertire un file audio in wav.

Codice: Seleziona tutto

#!/bin/sh
for i in $(ls *.$1)
do
    mplayer -ao pcm:fast "$i"
    rm $i
    mv audiodump.wav $(sed "s/\.$1$/.wav/")
done
Il problema è che, siccome i nomi dei file contengono anche degli spazi, mplayer prende solo la prima parola del nome.
Come si può risolvere?
E poi, si può sintetizzare l'intero script in un solo comando con una serie di xargs?

Re: Bash: xargs, variabili e spazi

Inviato: lun 9 giu 2008, 23:07
da umaga
io proverei "'$i'", cioe aggiungi le virgolette....

Re: Bash: xargs, variabili e spazi

Inviato: lun 9 giu 2008, 23:11
da targzeta
Se ne è parlato qualche volta sul forum. Dal man di bash:
IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is "<space><tab><newline>''.
Quindi se alla variabile IFS assegni quello che ti pare a te, non hai problemi. Ecco come si potrebbe sintetizzare il tuo script:

Codice: Seleziona tutto

IFS=$(echo -e '\n\t');   # Ora il separatore di campo è <newline> e <tab>.
for file in *.$1
  do
    mplayer -ao pcm:fast:file=${file%.$1}.wav $file
done
rm -f *.$1 # Ma io non lo farei
Spina

Re: Bash: xargs, variabili e spazi

Inviato: mar 10 giu 2008, 13:32
da anycolouryoulike
Grazie a tutti! Ho risolto modificando la variabile IFS.

Ho letto anche le altre discussioni e il man di bash, ma non riesco a capire delle cose...
Perché questi separatori hanno un ordine?
Perché non mettere ad esempio \t\n invece di \n\t?
Ma sopratutto, se lo spazio non separa più i comandi ad esempio rm -f *.$1 non dovrebbe restituire bash: rm -f *.$1: command not found?

Re: Bash: xargs, variabili e spazi

Inviato: mar 10 giu 2008, 14:51
da Mario Vanoni
anycolouryoulike ha scritto: Ma sopratutto, se lo spazio non separa più i comandi ad esempio rm -f *.$1 non dovrebbe restituire bash: rm -f *.$1: command not found?
rm(1) e` un commando, la bash(1) lo trova, anche senza argomenti,
rm -f == ignore nonexistent files, never prompt
rrmm -f *
bash: rrmm: command not found

Re: Bash: xargs, variabili e spazi

Inviato: mar 10 giu 2008, 15:39
da targzeta
anycolouryoulike ha scritto:....
Perché non mettere ad esempio \t\n invece di \n\t?
....
Questa domanda è carina, me la pose come domanda a trabocchetto il mio sistemista di laboratorio all'università (ed io ci cascai). In realtà, ora sono al lavoro e non ho linux, ma ci dovrebbe essere scritto nel man della bash che elimina l'ultimo \n, l'ordine non conta, se non fosse per questo. Infatti
"\ns\t" è uguale a "\n\ts". Il problema si pone solo se alla fine c'è un '\n', come descritto nel man della bash.

Spina

Re: Bash: xargs, variabili e spazi

Inviato: mar 10 giu 2008, 15:44
da anycolouryoulike
Continuo a non capire...
In questa situazione ad esempio:

Codice: Seleziona tutto

root@darkstar:~# IFS=$(echo -e '\n\t')
root@darkstar:~# ls
loadlin16c.txt  loadlin16c.zip
Se faccio ls loadlin16c.txt loadlin16c.zip me li lista tutti e due. Non dovrebbe considerarli come un file unico e darmi ls: cannot access loadlin16c.txt loadlin16c.zip: No such file or directory?
Lo spazio non separa più i campi, no?

Re: Bash: xargs, variabili e spazi

Inviato: mar 10 giu 2008, 15:47
da anycolouryoulike
spina ha scritto:
anycolouryoulike ha scritto:....
Perché non mettere ad esempio \t\n invece di \n\t?
....
Questa domanda è carina, me la pose come domanda a trabocchetto il mio sistemista di laboratorio all'università (ed io ci cascai). In realtà, ora sono al lavoro e non ho linux, ma ci dovrebbe essere scritto nel man della bash che elimina l'ultimo \n, l'ordine non conta, se non fosse per questo. Infatti
"\ns\t" è uguale a "\n\ts". Il problema si pone solo se alla fine c'è un '\n', come descritto nel man della bash.

Spina
Non ho capito una parola...
Prima meglio che mi legga il man.

Re: Bash: xargs, variabili e spazi

Inviato: mar 10 giu 2008, 16:37
da Paoletta
la cosa poteva anche essere risolta in questo modo:

Codice: Seleziona tutto

#!/bin/sh                                                                       
tmp=$(ls -1 *.$1)
for i in "$tmp"
do
    ...codice...
done

Re: Bash: xargs, variabili e spazi

Inviato: mer 11 giu 2008, 13:11
da anycolouryoulike
Leggendo man bash ho scoperto diverse cose.
man bash ha scritto:Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.
Quindi invece di usare un echo basta IFS=$'\t\n' e credo non ci sia nemmeno bisogno di mettere prima il \t perché non è una sostituzione di comando. Infatti nella sotituzione di comando viewtopic.php?p=66510#p66510...

La questione dell'ls loadlin16c.txt loadlin16c.zip ancora non l'ho capita però...
Qualcuno mi potrebbe chiarire le idee?

@Paoletta: questo mi dà lo stesso errore:

Codice: Seleziona tutto

#!/bin/sh
tmp=$(ls -1 *.wma)
for i in "$tmp"
do
    mplayer -ao pcm:fast:name=${i%.wma}.wav $i
done

Re: Bash: xargs, variabili e spazi

Inviato: ven 13 giu 2008, 13:47
da anycolouryoulike
Ma questa cosa funziona solo quando gli pare?

Codice: Seleziona tutto

root@darkstar:~# ls -1
loadlin16c.txt
loadlin16c.zip
prova.sh
root@darkstar:~# cat prova.sh
#!/bin/sh
IFS=$(echo -e '\n\t');
ls loadlin16c.txt loadlin16c.zip > log
root@darkstar:~# ./prova.sh
root@darkstar:~# cat log
loadlin16c.txt
loadlin16c.zip
root@darkstar:~# mkdir prova
root@darkstar:~# cd prova/
root@darkstar:~/prova# touch "loadlin16c.txt loadlin16c.zip"
root@darkstar:~/prova# ../prova.sh
ls: cannot access loadlin16c.txt: No such file or directory
ls: cannot access loadlin16c.zip: No such file or directory
root@darkstar:~/prova# ls -1
loadlin16c.txt loadlin16c.zip
log
root@darkstar:~/prova# cat log
root@darkstar:~/prova#

Re: Bash: xargs, variabili e spazi

Inviato: ven 13 giu 2008, 14:10
da Paoletta
dove mi trovo non ho nè mplayer nè il tempo per verificare; il mio esempio era solo per mostrare il fatto che con ls -1 si ha la possibilità di evirare il riassegnamento di IFS (cosa secondo me sensata, infatti se poi eseguo un altro script che fa conto sul valore "giusto" di IFS potrei avere dei malfunzionamenti); infatti:

Codice: Seleziona tutto

#!/bin/sh                                                                       
tmp=$(ls -1 *.wma)
for i in "$tmp"
do
    mplayer -ao pcm:fast "$i"
    rm "$i"
    mv audiodump.wav $(sed "s/\.$1$/.wav/")
done
dovrebbe funzionare; credo che in

Codice: Seleziona tutto

 mplayer -ao pcm:fast:file=${file%.$1}.wav $file
manchi qualche ""

Re: Bash: xargs, variabili e spazi

Inviato: sab 14 giu 2008, 0:26
da anycolouryoulike
Il problema quindi non è nella stringa di mplayer ma nel ciclo for...
Domani faccio un paio di prove, grazie.

Re: Bash: xargs, variabili e spazi

Inviato: dom 15 giu 2008, 14:28
da anycolouryoulike
Adesso credo di aver capito.
IFS lo usa solamente for per determinare i campi da passare in questo caso a mplayer. Anche con ls -1 conta anche gli spazi come separatori oltre ai ritorni a capo, e l'effetto quindi è lo stesso.
Non credo sia possibile senza modificare l'IFS. È l'unico modo per fare in modo che il for passi a mplayer i comandi riga per riga senza contare gli spazi.
Se ho capito male correggetemi pure.

Codice: Seleziona tutto

#!/bin/sh
IFS=$'\t\n'
for file in $(ls *.$1)
do
    mplayer -ao pcm:fast:file=${file%.$1}.wav $file
done
exit

Re: Bash: xargs, variabili e spazi

Inviato: dom 15 giu 2008, 22:08
da targzeta
Ciao,
innanzi tutto grazie per la dritta sul $'', si vede che, o mi è sfuggita oppure che l'hanno aggiunta da poco.....e devo dire meno male, ci si risparmia di eseguire un echo ogni volta che si vuole modificare IFS.

Quello che cerchi, lo trovi come "word splitting" sotto la sezione EXPANSION del man della bash.
In pratica che succede, se ai parametri viene fatta una 'espansione di parametro', una 'sostituzione di comando' oppure una 'espansione aritmetica', allora ai parametri viene fatto anche il 'word splitting', ovvero si divide il risultato di suddetta espensione in parole, usando come separatore di parole, ogni carattere contenuto nella variabile 'IFS'.

Facciamo degli esempi, impostando:

Codice: Seleziona tutto

IFS=$'a\n'
ovvero, come separatore di parole i caratteri 'a' e '\n'.

Esempio:

Codice: Seleziona tutto

\ls casa
ls: impossibile accedere a casa: No such file or directory
In questo caso, al parametro 'casa', la shell non ha fatto nessuna delle tre espansione su dette, quindi bash invoca 'ls' passandogli 'casa' come parametro.

Nel seguente esempio invece:

Codice: Seleziona tutto

casa="mamma"
\ls $casa
ls: impossibile accedere a m: No such file or directory
ls: impossibile accedere a mm: No such file or directory
al parametro '$casa' viene fatta l'espansione di parametro, per cui bash invoca 'ls' passandogli 'm' e 'mm'.

Ora dovrebbe esserti chiaro perchè, se IFS è impostata di default, quindi a '<spazio><tab><newline>', ed in una directory hai i file:
casa
ciao mamma
Ottieni due risultati differenti se esegui:

Codice: Seleziona tutto

for file in *; do  echo $file; done
casa
ciao mamma
e se esegui

Codice: Seleziona tutto

for file in $(\ls *); do  echo ${file}; done
casa
ciao
mamma
Ed anche perchè, nel thread, viewtopic.php?f=2&t=25031 hai detto una sciocchezzuola (riferendoti all'ultimo script postato da aschenaz) ;).

Ringraziandoti ancora per la dritta su $'' e con la speranza di esserti stato di aiuto,
Spina