Loop no script de shell dos arquivos de texto

4

Eu tenho uma lista de arquivos em um diretório e um conjunto de jpegs correspondentes a cada arquivo em outro diretório. Eu preciso fazer um loop em todos os arquivos e, para cada nome de arquivo, determinar o diretório de destino.

Por exemplo, se eu tiver três arquivos de texto chamados foo.txt , bar.txt e baz.txt in /home/userA/folder/ , os jpegs correspondentes estarão em /home/userA/folder2/foo/ , /home/userA/folder2/bar/ e /home/userA/folder2/baz/ .

Eu escrevi um script que deve fazer um loop em todos os arquivos txt e obter os diretórios de destino correspondentes, mas está me dando um erro:

bash: /home/userA/folder/File1.txt: syntax error: operand expected (error token is "/home/userA/folder/File1.txt")'

Meu script:

#!/bin/bash
FILES=/home/userA/folder/*.txt
for i in $FILES
do
    str1=$i | cut -d'/' -f5 #to get the name of the file
    echo /home/userA/folder2/$i_filename #I want to include the .txt filename in the output to be like this /home/userA/folder2/Text1_filename    
done

Como posso corrigir isso?

    
por Tak 24.06.2015 / 13:17

6 respostas

1

Usando find :

#!/bin/bash
path="/home/userA/folder"
find "$path" -maxdepth 1 -type f -name "*.txt" -print0 | while read -d $'
#!/bin/bash
path="/home/userA/folder"
find "$path" -maxdepth 1 -type f -name "*.txt" -print0 | while read -d $'%pre%' file; do
    a="$path/$(basename $file)/a_%06.jpg"
    echo "$a
done
' file; do a="$path/$(basename $file)/a_%06.jpg" echo "$a done
    
por 24.06.2015 / 15:31
2

Se tudo que você quer é pegar o nome do arquivo e usá-lo para obter o diretório de destino certo, você pode fazer:

#!/bin/bash
for i in /home/userA/folder/*.txt
do
    ## Get the file name
    str1="${i##*/}"

    ## Get the target directory
    dir="/home/userA/folder2/${str1%.txt}/"
done

Isso está usando os recursos nativos manipulação de string do shell. ${var##pattern} remove a correspondência mais longa de pattern do início de $var e ${var%pattern} remove a correspondência mais curta de pattern do final de $var . Portanto, ${i##*/} remove tudo até o último / (o caminho) do nome do arquivo e ${i%.txt} remove a string .txt do final dele.

    
por 24.06.2015 / 16:05
1

Você acabou de esquecer as echo e as backquotes e o número do campo nessa linha

    str1='echo $i | cut -d'/' -f5 '#to get the name of the file

Mas basename pode ser uma opção melhor.

    str1='basename $i' #name of the file

Como isso

#!/bin/bash
FILES=/home/userA/folder/*.txt
for i in $FILES
do
    str1='basename "$i"' #to get the name of the file
    echo $str1
    ls -l "'dirname "$i"'/$str1"
done

Para uma boa resposta sobre como lidar com loops e arquivos com espaços em seu nome, consulte Esta resposta

    
por 24.06.2015 / 13:27
1

Você quer dizer isso?

 ~/test $ for i in F/*.txt; do n="TARGET/$(basename "$i" .txt)"; echo "$n"; done
TARGET/a
TARGET/b
TARGET/c
 ~/test $ ls F
a.txt  b.txt  c.txt
 ~/test $

E com caracteres e espaços especiais:

 ~/test $ for i in F/*.txt; do n="TARGET/$(basename "$i" .txt)"; echo "\"$n\""; done
"TARGET/a b€C\""
"TARGET/a"
"TARGET/b"
"TARGET/c"
 ~/test $ ls F
a b€C\".txt  a.txt  b.txt  c.txt
    
por 24.06.2015 / 16:24
0

Se você realmente quiser colocá-lo em uma variável, você pode usar uma matriz bash:

#!/bin/bash
FILES=(/home/userA/folder/*.txt)
for i in "${FILES[@]}" # double qouting pervents extra word splitting
do
    bn="$(basename "$i")" # to get the name of the file
    a="/home/userA/folder2/$bn/a_%06d.jpg"
done

Ou você pode simplesmente usar for i in /home/userA/folder/*.txt .

    
por 24.06.2015 / 15:26
0
find /home/userA/folder/ -maxdepth 1 -type f -name "*.txt" -print0 | while read -r -d '' file; do filename=$(printf "%s\n" "$file" | awk -F'/' '{gsub(".txt","");print $5}' ); printf "/home/userA/folder2/%s" "$filename"; done
    
por 24.06.2015 / 15:12