Tengo una lista de archivos que quiero verificar si existen en mi sistema de archivos. Pensé en hacer esto usando find
como en:
for f in $(cat file_list); do
find . -name $f > /dev/null || print $f
done
(usando zsh
) pero eso no funciona ya que find
parece salir 0
si encuentra o no el archivo. Supongo que podría pasarlo por alguna otra prueba, que prueba para ver si find
produce algo (crudo pero efectivo sería reemplazarlo > /dev/null
con |grep ''
), pero esto se siente como usar un troll para atrapar una cabra (otras nacionalidades podrían decir algo sobre mazos y nueces )
¿Hay alguna manera de find
obligarme a darme un valor de salida útil? ¿O al menos para obtener una lista de esos archivos que no se encontraron? (Me imagino que esto último es quizás más fácil por alguna astuta elección de conexiones lógicas, pero parece que siempre me atoro cuando trato de resolverlo).
Antecedentes / Motivación: Tengo una copia de seguridad "maestra" y quiero verificar que existan algunos archivos en mi máquina local en mi copia de seguridad maestra antes de eliminarlos (para crear un poco de espacio). Así que hice una lista de los archivos, los ssh
edité en la máquina maestra, y luego no pude encontrar la mejor manera de encontrar los archivos faltantes.
locate
.locate
no muestra el estado actual del sistema de archivos, podría ser un día o incluso una semana de antigüedad. Eso es adecuado como base para probar las copias de seguridad.Respuestas:
find
considera no encontrar nada un caso especial de éxito (no se produjo ningún error). Una forma general de probar si los archivos coinciden con algunosfind
criterios es probar si la salida defind
está vacía. Para una mejor eficiencia cuando hay archivos coincidentes, use-quit
en GNU find para que se cierre en la primera coincidencia, ohead
(head -c 1
si está disponible, de lo contrario, lohead -n 1
que es estándar) en otros sistemas para que muera por una tubería rota en lugar de producir una salida larga.En bash ≥4 o zsh, no necesita el
find
comando externo para una simple coincidencia de nombre: puede usar**/$name
. Versión bash:Versión de Zsh con un principio similar:
O aquí hay una forma más corta pero más críptica de probar la existencia de un archivo que coincida con un patrón. El calificador global
N
hace que la salida esté vacía si no hay coincidencia,[1]
conserva solo la primera coincidencia ye:REPLY=true:
cambia cada coincidencia para expandirla en1
lugar del nombre del archivo coincidente. Entonces se**/"$name"(Ne:REPLY=true:[1]) false
expande atrue false
si hay una coincidencia, o simplemente afalse
si no hay coincidencia.Sería más eficiente combinar todos sus nombres en una sola búsqueda. Si el número de patrones no es demasiado grande para el límite de longitud de su sistema en una línea de comando, puede unir todos los nombres
-o
, hacer una solafind
llamada y procesar posteriormente la salida. Si ninguno de los nombres contiene metacaracteres de shell (de modo que los nombres también sonfind
patrones), esta es una forma de postprocesar con awk (no probado):Otro enfoque sería usar Perl y
File::Find
, lo que facilita la ejecución del código Perl para todos los archivos en un directorio.Un enfoque alternativo es generar una lista de nombres de archivos en ambos lados y trabajar en una comparación de texto. Versión Zsh:
fuente
zsh
solución con la**
sintaxis. Es una solución muy simple y, si bien puede que no sea la más eficiente en términos de máquina , ¡probablemente sea la más eficiente en términos de que realmente lo recuerde! Además, la primera solución aquí responde a la pregunta real en que se tuercefind
en algo donde el código de salida distingue "Tengo una coincidencia" de "No obtuve una coincidencia".Puede usarstat
para determinar si existe un archivo en el sistema de archivos.Debe usar las funciones de shell incorporadas para probar si existen archivos.
La "prueba" es opcional y el script realmente funcionará sin él, pero lo dejé allí para facilitar la lectura.
Editar: si realmente no tiene más opción que trabajar para una lista de nombres de archivo sin rutas, le sugiero que cree una lista de archivos una vez con find, luego repítala con grep para descubrir qué archivos hay.
Tenga en cuenta que:
fuente
Un primer enfoque simplista podría ser:
a) ordenar su lista de archivos:
para encontrar faltas, o
para encontrar coincidencias
Inconvenientes:
find podría buscar varios archivos a la vez, con cierta preparación:
find -name a.file -or -name -b.file -or -name c.file ...
¿Podría ser una opción? Una vez más, se supone una lista clasificada de archivos:
Una búsqueda de foo.bar no coincidirá con un archivo foo.ba u oo.bar con --regexp-construct (no debe ser confundido por regex sin p).
Puede especificar una base de datos específica para localizar, y debe actualizarla antes de buscar, si necesita los resultados más recientes.
fuente
Creo que esto también puede ser útil.
Esta es una solución de una línea, en caso de que opte por que su "lista" sea archivos reales que desea sincronizar con otra carpeta:
para ayudar a leer:
este ejemplo excluye los archivos de respaldo "* ~" y limita el tipo de archivo normal "-type f"
fuente
¿Tal vez?
fuente
¿Por qué no simplemente comparar la longitud de la lista de consultas con la longitud de la lista de resultados?
fuente