Ya descubrió la razón inmediata por la que su código no hizo lo que esperaba:errores de ls
se informan a stderr (como lo sugiere POSIX), que no se captura como entrada por la canalización. Por lo tanto, obtuvo una mezcla de salida normal (que pasó sin cambios por su sed
declaraciones) y stderr (que los omitió). No sé por qué tu ls
salida cambiada entre llamadas; redirigir stdout a /dev/null debería tener el efecto de eliminar todas las "normales" (rutas existentes) de la salida. La solución para esto es no para meter stderr en stdout, sin embargo.
Procesamiento posterior de la salida de ls
es una idea peligrosa si quieres un script confiable. Un buen artículo sobre el tema es "Por qué no debería analizar la salida de ls(1)", disponible en el sitio wooledge.org. Una sesión de preguntas y respuestas en profundidad en el sitio de Unix y Linux aborda algunos de los problemas:¿Por qué no? analizar ls
(y qué hacer en su lugar)?. El resultado es que los nombres de archivo UNIX pueden contener casi cualquier carácter, incluidos espacios, tabuladores, líneas nuevas, comillas simples, comillas dobles, comillas simples con escape, etc. Para algunos ejemplos rápidos, considere los directorios con estos nombres, todos los cuales son perfectamente legales:
- "No existe tal archivo" (
mkdir "No such file"
) - "ls:no se puede acceder a 'foo':No existe tal archivo o directorio" (
mkdir "ls: cannot access 'foo': No such file or directory"
) -
"directorio
con
incrustado
líneas nuevas" (
mkdir $'directory\nwith\nembedded\newlines'
)
El primero es un directorio inocente que el grep
captura incorrectamente (de stdout) . El segundo también se captura por error, pero luego se destroza aún más en un camino completamente diferente. ¡que puede o no existir! -- por el sed
declaraciones. El tercero es un ejemplo de lo que sucede cuando pasas la salida de ls
en programas orientados a la línea; si el directorio no existe, ls
lo dirá en más de una línea, que es probablemente la forma en que terminó con dos sed
separados declaraciones!
Para distinguir las "buenas rutas" (las que existen y son legibles) de las "malas rutas", sugeriría recorrer la matriz y crear nuevas matrices de cada una.
for p in "${paths[@]}"
do
if [ -r "$p" ]
then
goodpaths+=("$p")
else
badpaths+=("$p")
fi
done
Luego puedes hacer lo que quieras con cada conjunto:
printf 'Good path: -->%s<--\n' "${goodpaths[@]}"
echo
printf 'Bad path: -->%s<--\n' "${badpaths[@]}"