Bucle en script de shell de files de text

Tengo una list de files en un directory y un set de jpegs correspondiente a cada file en otro directory. Necesito recorrer todos los files y, para cada nombre de file, determinar el directory de destino.

Por ejemplo, si tengo tres files de text llamados foo.txt , bar.txt y baz.txt en /home/userA/folder/ , los jpegs correspondientes estarán en /home/userA/folder2/foo/ , /home/userA/folder2/bar/ and /home/userA/folder2/baz/ .

Escribí un script que debería recorrer todos los files txt y get los directorys de destino correspondientes, pero me da un error:

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

Mi guion

 #!/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 

¿Cómo puedo arreglar esto?

Usando find :

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

Si todo lo que desea es get el nombre del file y usarlo para get el directory de destino correcto, puede hacer lo siguiente:

 #!/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 

Esto está usando las características de manipulación de cadenas nativas del shell. ${var##pattern} elimina la coincidencia más larga del pattern desde el inicio de $var y ${var%pattern} elimina la coincidencia más corta del pattern desde el final de $var . Entonces, ${i##*/} elimina todo hasta la última / (la ruta) del nombre del file y ${i%.txt} elimina la cadena .txt del final de la misma.

Simplemente olvidas el echo y las comillas inversas y el número de campo en esta línea

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

Pero basename podría ser una mejor opción.

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

Me gusta esto

 #!/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 get una buena respuesta sobre cómo tratar con loops for y files con espacios en su nombre, consulte Esta respuesta

¿Quieres decir esto?

  ~/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 $ 

Y con caracteres especiales y espacios:

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

Si realmente quieres ponerlo en una variable, puedes usar una matriz de 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 

O simplemente puede usar for i in /home/userA/folder/*.txt .

 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