PDA

View Full Version : Shell unix per ordinare file in cartelle


power83
27-10-2008, 15:19
Buongiorno a tutti,
dovrei creare una shell unix che analizza il contenuto di
una cartella e ordina i vari file in sottocartelle.
Ad es nella cartella sono presenti i file a1.txt, a2.txt, b1.txt
il risultato sarebbe avere i file 'a' tutti dentro la sottocartella 'filea'
e i file 'b' tutti dentro la sottocartella 'fileb'.

E' possibile una cosa del genere, se si come?!?

Grazie

leuzr0x
27-10-2008, 16:43
Cosa intendi per creare una shell unix?
Scrivere una shell da 0 che ti permetta di fare cio' che dici tu, o uno script per una shell
gia' esistente (es bash) ?

power83
27-10-2008, 16:45
Cosa intendi per creare una shell unix?
Scrivere una shell da 0 che ti permetta di fare cio' che dici tu, o uno script per una shell
gia' esistente (es bash) ?


Ciao, scriverla da 0! :cry:

dawid999
27-10-2008, 16:59
Ciao, scriverla da 0! :cry:

script di shell ;)

power83
27-10-2008, 17:10
script di shell ;)

Sfortunatamente le mie conoscenze di unix sono pochine...potresti spiegarmi cosa intendi?!?

Grazie

megamitch
27-10-2008, 17:57
Ciao,
quello che ti serve è uno "script" (o un programma se preferisci) che esegua le operazioni che ti servono.

La "shell" è l'ambiente dentro il quale il programma (o script) viene eseguito.

Ciao
M.

PS: per i puristi, non vogliatemene se ho usato un linguaggio "scorretto"... :)

leuzr0x
27-10-2008, 19:07
script di shell ;)

Si credo anch'io :p
Ma magari parlava di un progetto universitario o chissa' cosa :)
Facci sapere se ti serve uno script.

HexDEF6
27-10-2008, 20:15
ti posto una cosa che mi e' venuta di getto (non l'ho testato, quindi potrei aver fatto qualche cazzata, ma l'idea di base c'e')...
ma ovviamente ti consiglio di studiarti almeno un pelino di bash (almeno sapere cos'e' una shell e cosa uno script!)


#!/bin/bash
for file in $(ls *.txt)
do
directory=file$(echo $file | cut -c 1)
mkdir -p $(pwd)/$directory
mv $file $directory/
done


a dire la verita' adesso che ci ho pensato 10 secondi in piu' mi e' venuto in mente un metodo decisamente piu' veloce (se ci sono tanti file)...
ma adesso vado ad allenamento... magari posto piu' tardi!

ok avevo 5 minuti :D


#!/bin/bash
for letter in $(ls *.txt | cut -c 1 | uniq)
do
mkdir -p ./file$letter
mv $letter*.txt ./file$letter
done

power83
28-10-2008, 17:37
Ciao,
quello che ti serve è uno "script" (o un programma se preferisci) che esegua le operazioni che ti servono.

La "shell" è l'ambiente dentro il quale il programma (o script) viene eseguito.

Ciao
M.

PS: per i puristi, non vogliatemene se ho usato un linguaggio "scorretto"... :)

Corretto...scusate la terminologia errata!
Ed è appunto un prgetto universitario!
Ci provo subito, grazie mille

Ps.: un ulteriore precisazione i nome dei file è a0001.txt .. a0011.txt e la cartella per uno sarà
cartella1 mentre per l'altro cartella11.

HexDEF6
28-10-2008, 19:12
Corretto...scusate la terminologia errata!
Ed è appunto un prgetto universitario!
Ci provo subito, grazie mille

Ps.: un ulteriore precisazione i nome dei file è a0001.txt .. a0011.txt e la cartella per uno sarà
cartella1 mentre per l'altro cartella11.

beh le basi te le ho fatte vedere... adesso con una buona guida: http://tldp.org/LDP/abs/html/ e un po di buona volonta' vedrai che ce la fai a modificare lo script e a fare quello che ti serve...
ovviamente per suggerimenti e spiegazioni, ti do' una mano volentieri...
magari studia un attimo e poi posta il tuo script (con spiegazione di quello che vuoi fare quasi riga per riga) e noi ti diamo una mano a sistemare!

buon lavoro!

Mason
29-10-2008, 00:29
Corretto...scusate la terminologia errata!
Ed è appunto un prgetto universitario!
Ci provo subito, grazie mille

Ps.: un ulteriore precisazione i nome dei file è a0001.txt .. a0011.txt e la cartella per uno sarà
cartella1 mentre per l'altro cartella11.

Almeno ci hai provato a farlo?

per policy, questi post dovrebbero essere corredati dal codice che uno prova a scrivere.

power83
29-10-2008, 10:37
Almeno ci hai provato a farlo?

per policy, questi post dovrebbero essere corredati dal codice che uno prova a scrivere.

Certo che ci ho provato...

Grazie HexDEF6 per il manuale!!

Ora ci picchio un pò la testa!

Graziiiiiiiieeeeee!

power83
30-10-2008, 09:36
Ciao a tutti,
grazie ai vostri consigli e al manuale sono riuscito a fare tutto il progetto
e non solo la piccola parte di cui chiedevo!

Mi sono restati due dubbi:
1) substring: sui vari manuali ho trovato questo codice:
stringZ=abcABC123ABCabc
echo `expr match "$stringZ" 'abc[A−Z]*.2'`
echo `expr "$stringZ" : 'abc[A−Z]*.2'`

Provando ad eseguirlo l'output a video sono giustamente due 8...in quanto la stringa abc o ABC è ripetuta 4 volte.
Ma non ne esiste un substring che faccia una cosa del genedere:
stringZ=abcABC123ABCabc
echo substr($stringZ,6,3)
Il cui output a video sarà in questo caso 123.

2) raplace: in questo caso, sempre sui manuali, ho trovato che il
replace si può fare con le seguenti istruzioni:
stringZ=abcABC123ABCabc
echo ${stringZ/#abc/XYZ}
echo ${stringZ/%abc/XYZ}

In entrambi i casi il risultato è bad substitution.
Quindi come posso sostituire una parte di da una stringa, esempio:
stringZ=abcABC123ABCabc
echo replace($stringZ,abc,'')
Il cui output a video sarà in questo caso ABC123ABC.

Scusate le domande sicuramente banali ma è la prima volta che mi "scontro"
con questo modo di scrivere programmi.

Grazie mille

HexDEF6
30-10-2008, 10:34
Ciao a tutti,
grazie ai vostri consigli e al manuale sono riuscito a fare tutto il progetto
e non solo la piccola parte di cui chiedevo!

Mi sono restati due dubbi:
1) substring: sui vari manuali ho trovato questo codice:
stringZ=abcABC123ABCabc
echo `expr match "$stringZ" 'abc[A−Z]*.2'`
echo `expr "$stringZ" : 'abc[A−Z]*.2'`

Provando ad eseguirlo l'output a video sono giustamente due 8...in quanto la stringa abc o ABC è ripetuta 4 volte.
Ma non ne esiste un substring che faccia una cosa del genedere:
stringZ=abcABC123ABCabc
echo substr($stringZ,6,3)
Il cui output a video sarà in questo caso 123.



se ho capito cosa ti serve, si fa cosi:
echo ${stringZ:6:3}


2) raplace: in questo caso, sempre sui manuali, ho trovato che il
replace si può fare con le seguenti istruzioni:
stringZ=abcABC123ABCabc
echo ${stringZ/#abc/XYZ}
echo ${stringZ/%abc/XYZ}

In entrambi i casi il risultato è bad substitution.
Quindi come posso sostituire una parte di da una stringa, esempio:
stringZ=abcABC123ABCabc
echo replace($stringZ,abc,'')
Il cui output a video sarà in questo caso ABC123ABC.

Scusate le domande sicuramente banali ma è la prima volta che mi "scontro"
con questo modo di scrivere programmi.

Grazie mille

stai usando una bash?
perche' le sostituzioni funzionano proprio cosi!

stringZ=abcABC123ABCabc
echo ${stringZ/#abc/XYZ}
il risultato sara' :
XYZABC123ABCabc
il # davanti indica che fara' la sostituzione solo se abc e' all'inizio della stringa

echo ${stringZ/%abc/XYZ}
il risultato sara':
abcABC123ABCXYZ
il % sta ad indicare che la sostituzione verra' fatta solo se la fine della stringa e' abc

se invece vuoi sostituire tutte le ricorrenze devi fare:
echo ${stringZ//abc/XYZ}
XYZABC123ABCXYZ
o se metti:
echo ${stringZ//abc/}
otterrai:
ABC123ABC

spero di aver chiarito!

power83
30-10-2008, 10:48
Ok, tutto chiaro...solo che sia per
echo ${stringZ:6:3} che per
echo ${stringZ//abc/}
il risultato è
${stringZ:6:3}: bad substitution
${stringZ//abc/}: bad substitution

Grazie mille per la spiegazione

HexDEF6
30-10-2008, 10:52
Ok, tutto chiaro...solo che sia per
echo ${stringZ:6:3} che per
echo ${stringZ//abc/}
il risultato è
${stringZ:6:3}: bad substitution
${stringZ//abc/}: bad substitution

Grazie mille per la spiegazione

ma che sistema operativo stai usando?
che shell?
perche' queste funzionano sicuramente sotto bash (le ho provate proprio adesso!)... ma magari sotto qualche altra shell no...

prima di lanciare uno di questi script lancia:
bash

e poi vai con lo script

power83
30-10-2008, 11:02
SunOS 5.8
Neanche sotto bash funzionano:

bash-2.03$ prova.sh
file_0001.txt
file_0011.dat
file_0012.dat
/shell/prova.sh[34]: ${stringZ:6:3}: bad substitution
bash-2.03$

Grazie

HexDEF6
30-10-2008, 11:47
SunOS 5.8
Neanche sotto bash funzionano:

bash-2.03$ prova.sh
file_0001.txt
file_0011.dat
file_0012.dat
/shell/prova.sh[34]: ${stringZ:6:3}: bad substitution
bash-2.03$

Grazie

azz, la guida credo si riferisca alla versione 3 di bash...
e infatti nel mio caso:
$ bash --version
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.

power83
30-10-2008, 12:04
Infatti noi abbaimo una misera version 2.03.0(1)-release...:muro:

Secondo te ci sono alternative?!?

Grazie

HexDEF6
30-10-2008, 12:22
Infatti noi abbaimo una misera version 2.03.0(1)-release...:muro:

Secondo te ci sono alternative?!?

Grazie

beh, puoi usare sed e awk, ma per fare certe cose come modificare una stringa, mi sembrano un pelo esagerati...

vedo se magari trovo la versione dell'advanced bash scripting guide per la bash 2

dovresti trovarti la guida alla versione 2.8
dalla 3 in poi inizia a parlare anche di bash 3

power83
30-10-2008, 12:32
Ok...visto che cmq andrei a lavorare sulla stessa stringa e solo in una particolare condizione provo anche sed e awk!

Grazie mille

power83
30-10-2008, 14:21
Con sed e awk è un casino...per quella parte devo inventare altro...! :)

power83
03-11-2008, 15:09
Mi ricollego a questo argomento:
sono cotretto ad untilizzare l'awk quindi:

for file in $(ls $Dir_Orig*.txt)
do
print $file
num = `awk '{substr($file,1,2)'}`
echo $num
if [ "$num" < "10" ]; then
echo minore di 10
Dir_dest = Dir_dest + $num
mv $file $Dir_dest
else
echo maggiore di 10
Dir_dest = Dir_dest + 1 + $num
mv $file $Dir_dest
fi
done

Il problema è che sembra restare il loop sull'awk...rimane fermo dopo il print del file e non si muove +...qualcuno sa dirmi il perchè?!? :p

HexDEF6
03-11-2008, 16:30
Mi ricollego a questo argomento:
sono cotretto ad untilizzare l'awk quindi:

for file in $(ls $Dir_Orig*.txt)
do
print $file
num = `awk '{substr($file,1,2)'}`
echo $num
if [ "$num" < "10" ]; then
echo minore di 10
Dir_dest = Dir_dest + $num
mv $file $Dir_dest
else
echo maggiore di 10
Dir_dest = Dir_dest + 1 + $num
mv $file $Dir_dest
fi
done

Il problema è che sembra restare il loop sull'awk...rimane fermo dopo il print del file e non si muove +...qualcuno sa dirmi il perchè?!? :p

cosi a occhio (pensando che hai una bash 2 sotto sunos)... potrebbe essere che awk non sa cosa sia $file...

prova cosi (al posto di: num = `awk '{substr($file,1,2)'}`)
num = `awk -v file=$file '{substr(file,1,2)'}`

e dimmi se funziona o magari cosi:
num=$(awk -v file=$file '{substr(file,1,2)'})

power83
03-11-2008, 16:40
nulla...sempre

awk: syntax error near line 1
awk: bailing out near line 1

:mc:

HexDEF6
03-11-2008, 16:59
nulla...sempre

awk: syntax error near line 1
awk: bailing out near line 1

:mc:

avrai anche una versione di awk del 1902 :D
cazzarola ma perche' un sunos di 10 ani fa?????????

vai di man awk e vedi come passargli variabili
o magari nel tuo scipt metti un print $file (dentro l'awk prima di tutto il resto) in modo da vedere se la variabile viene passata...

power83
03-11-2008, 17:09
Ehehe...sfortunatamente non dipende da me...:cry: mi devo prendere macchina fatta e finita...senza possibilità di modificare nulla! :cry:

HexDEF6
03-11-2008, 17:26
#!/bin/bash
Dir_Orig="./"
echo $Dir_Orig
for file in $(ls $Dir_Orig*.txt)
do
echo "il nome del file: " $(basename $file)
num=$(echo $(basename $file) | awk '{ print substr($0,2,2) }')
echo $num
if [ "$num" -lt "10" ]; then
echo minore di 10
Dir_dest=$num
mkdir -p $Dir_dest
mv $file $Dir_dest
else
echo maggiore di 10
Dir_dest=$num
mkdir -p $Dir_dest
mv $file $Dir_dest
fi
done


questo dovrebbe funzionare per file fatti cosi:
a01.txt ==> nella dir 01
a02.txt ==> nella dir 02
a03.txt ==> nella dir 03
b01.txt ==> nella dir 01
c01.txt ==> nella dir 01
c02.txt ==> nella dir 02

l'if non serve ad un tubo (a parte stampare se il numero e' maggiore o minore di 10)

power83
03-11-2008, 17:31
#!/bin/bash
Dir_Orig="./"
echo $Dir_Orig
for file in $(ls $Dir_Orig*.txt)
do
echo "il nome del file: " $(basename $file)
num=$(echo $(basename $file) | awk '{ print substr($0,2,2) }')
echo $num
if [ "$num" -lt "10" ]; then
echo minore di 10
Dir_dest=$num
mkdir -p $Dir_dest
mv $file $Dir_dest
else
echo maggiore di 10
Dir_dest=$num
mkdir -p $Dir_dest
mv $file $Dir_dest
fi
done


questo dovrebbe funzionare per file fatti cosi:
a01.txt ==> nella dir 01
a02.txt ==> nella dir 02
a03.txt ==> nella dir 03
b01.txt ==> nella dir 01
c01.txt ==> nella dir 01
c02.txt ==> nella dir 02

l'if non serve ad un tubo (a parte stampare se il numero e' maggiore o minore di 10)

Provo a fare alre prove...!

Mason
04-11-2008, 00:22
secondo me al posto del awk sarebbe meglio usare il cut -c

power83
04-11-2008, 10:13
ho fatto così e sembra funzionare correttamente...

for num in `ls $Dir_Orig*.dat | awk '{ print substr($0, 6,3) }'`

provo con qualche caso particolare!

Grazie mille a tuttiiiiiiiiii! :)