
Supongamos que tengo 2 bucles separados
for file1 in `ls Dir1/` ; do
echo $file1
done
for file2 in `ls Dir2/` ; do
echo $file2
done
Quiero que un bucle único itere el pseudocódigo de ambos directorios.
for file1 , file2 in `ls Dir1` , `ls Dir2`
do
echo $file1
echo file2
done
Es posible
Respuesta1
Un while
bucle con una entrada adecuada puede hacer el trabajo, suponiendo que no haya caracteres de nueva línea en los nombres de los archivos.
paste -d/ <(ls /var) <(ls /usr) |
while IFS=/ read -r e u; do
printf '%s\n' "$e $u"
done
Respuesta2
shopt -s nullglob
dir1names=( Dir1/* )
dir2names=( Dir2/* )
while [ "${#dir1names[@]}" -gt 0 ] &&
[ "${#dir2names[@]}" -gt 0 ]
do
printf '%s\n' "${dir1names[0]##*/}"
printf '%s\n' "${dir2names[0]##*/}"
dir1names=( "${dir1names[@]:1}" )
dir2names=( "${dir2names[@]:1}" )
done
Esto se utiliza bash
para obtener todos los nombres de ruta de cada directorio en dos matrices. Luego imprime la parte del nombre de archivo de estos nombres de ruta (como ls
lo haría), alternando entre las matrices, y elimina los elementos completos impresos de las matrices. Se detiene cuando una de las matrices está completamente vacía.
La nullglob
opción Shell hace que los patrones globales no coincidentes se expandan hasta quedar en nada en lugar de permanecer sin expandir.
Pruebas:
$ tree
.
|-- Dir1
| |-- file-1
| |-- file-2
| |-- file-3
| `-- file-4
|-- Dir2
| |-- otherfile-1
| |-- otherfile-2
| |-- otherfile-3
| |-- otherfile-4
| |-- otherfile-5
| `-- otherfile-6
`-- script.sh
2 directories, 11 files
$ bash script.sh
file-1
otherfile-1
file-2
otherfile-2
file-3
otherfile-3
file-4
otherfile-4
Si esto esde hechoacerca de emparejar archivos según sus nombres, de modo que un archivo en un directorio se empareje con el archivo correspondiente en otro (como parece que a veces se hace, por ejemplo, en aplicaciones bioinformáticas), entonces es mejor simplemente iterar sobre uno de los conjuntos y luegoconstruyendoel nombre de los archivos correspondientes del otro conjunto.
Suponiendo que se llaman los archivos something_R1_more
y something_R2_more
dónde something
se more
identifica un par de archivos R1
en particular.R2
for r1 in dir1/*_R1_*; do
r2=${r1##*/} # dir1/something_R1_more --> something_R1_more
r2=dir2/${r2/_R1_/_R2_} # something_R1_more --> dir2/something_R2_more
if [ ! -f "$r2" ]; then
printf '%s not found\n' "$r2" >&2
exit 1
fi
# process "$r1" and "$r2" here
done
Respuesta3
tu generalmenteno quiero analizar la salida dels
.
Aquí, con zsh
(ya estás usando zsh
la sintaxis, no bash
porque no estás citando tus variables y usando la sustitución de comandos sin deshabilitar el globbing), podrías hacer:
dir1_file_names=(dir1/*(N:t))
dir2_file_names=(dir2/*(N:t))
for f1 f2 (${dir1_file_names:^dir2_file_names})
printf '%s\n' "f1: $f1, f2: $f2"
zsh
Puede realizar un bucle con varias variables. ${a:^b}
es uncompresión de matricesoperador. Si uno de los arrays tiene menos elementos que el otro, será como si estuvieran truncados a la longitud del más pequeño.
Vea también sus operadores de intersección y resta de matrices si se trata de comparar los nombres de archivos en los dos directorios:
file_names_in_both_dir1_and_dir2=(${dir1_file_names:*dir2_file_names})
file_names_only_in_dir1=(${dir1_file_name:|dir2_file_names})
file_names_only_in_dir2=(${dir2_file_name:|dir1_file_names})
Respuesta4
La salida de múltiples variables se puede guardar en una sola variable como se menciona a continuación. Comprueba si te funciona
#!/bin/bash
cd /
for file1 in $(ls /usr/ ; echo "::::::NEXT:::::::" ; ls /sys/)
do
echo $file1
done