¿Cómo enumero un nombre de archivo por línea de salida en Linux?


229

Estoy usando el ls -acomando para obtener los nombres de archivo en un directorio, pero la salida está en una sola línea.

Me gusta esto:

.  ..  .bash_history  .ssh  updater_error_log.txt

Necesito una alternativa integrada para obtener nombres de archivo, cada uno en una nueva línea, como esta:

.  
..  
.bash_history  
.ssh  
updater_error_log.txt

3
ls está destinado a mostrar una lista para el consumo humano. Si está utilizando ls para cualquier otro propósito (como, por ejemplo, para obtener una lista de archivos en un script para iterar), seguramente está utilizando la herramienta incorrecta.
Juliano

2
@juliano: en realidad, debe ser consumido por un script de Python. ¿Por qué lo llamas una herramienta incorrecta?
Fixxxer

1
@fixxer En el momento en que se conecte lsa Python, lsgenerará un archivo por línea como lo expliqué en mi respuesta.
Peter G.

66
@fixxxer: Entonces lo estás usando mal. Formatea el listado para salida en el terminal de usuario. Puede reemplazar caracteres especiales en el nombre del archivo, puede omitir caracteres que tengan un significado especial, etc. En otras palabras, ls formatea una lista para el usuario. Desea nombres de archivo sin formato. ¿Alguna razón especial por la que no está utilizando el módulo 'glob' de python? docs.python.org/library/glob.html También hay 'fnmatch', 'dircache' y otros.
Juliano

@fixxer ¿Realmente has realizado la lssalida pythony observado la salida de una sola línea en python?
Peter G.

Respuestas:


430

Use la -1opción (tenga en cuenta que este es un "un" dígito, no una letra minúscula "L"), de esta manera:

ls -1a

Primero, sin embargo, asegúrese de lscontar con su apoyo -1. GNU coreutils (instalado en sistemas Linux estándar) y Solaris do; pero en caso de duda, utilice man lso ls --helpo compruebe la documentación. P.ej:

$ man ls
...
       -1     list one file per line.  Avoid '\n' with -q or -b

2
+1 No sabía acerca de -1 (-l sí (ell no uno)) Se muestra en la página de manual pero lo he estado leyendo como
unll

@slashmais - Ah, buen punto - fácil de confundir. Aclaré en la respuesta.
Bert F

1
@dty: para GNU, obtienes esto documentado en la ls --helpsalida ... siempre instalado ;-)
Tony Delroy

3
Busqué en Google linux ls one file per liney este fue el artículo principal. No puedo creer cuán prolija es la respuesta elegida o que esta respuesta tiene menos votos que la que se dirige al gato. ls -1ftw.
crantok

3
lsel -1comportamiento predeterminado es cuando la salida no está conectada al terminal.
codeforester

132

Sí, puede hacer que la lssalida sea un nombre de archivo por línea:

ls -a | cat

Explicación: El comando lsdetecta si la salida es a un terminal o a un archivo o tubería y se ajusta en consecuencia.

Entonces, si se conecta ls -aa Python, debería funcionar sin ninguna medida especial.


2
Wow, esto es genial. La ventaja sobre la respuesta aceptada: esta realmente funciona en Android / adb shell, donde lssolo hay una versión -1
simplificada,

¿Cómo puede evitar los .y .."archivos" que muestran en la salida, aunque?
matanster

@matanster: Depende, ¿quieres ver archivos de puntos? Si no, simplemente suelte la opción -a.
Peter G.

29

Ls está diseñado para el consumo humano, y no debe analizar su salida .

En los scripts de shell, hay algunos casos en los que analizar la salida de ls funciona es la forma más sencilla de lograr el efecto deseado. Dado que ls puede alterar caracteres que no son ASCII y controlar los nombres de los archivos, estos casos son un subconjunto de aquellos que no requieren la obtención de un nombre de archivo ls.

En python, no hay absolutamente ninguna razón para invocar ls. Python tiene todas lslas funciones integradas. Utilícelo os.listdirpara enumerar el contenido de un directorio y / os.stato ospara obtener metadatos de archivo. osEs probable que otras funciones en los módulos también sean relevantes para su problema.


Si está accediendo a archivos remotos a través de ssh, una forma razonablemente sólida de enumerar nombres de archivos es a través de sftp:

echo ls -1 | sftp remote-site:dir

Esto imprime un nombre de archivo por línea y, a diferencia de la lsutilidad, sftpno destruye los caracteres no imprimibles. Aún no podrá enumerar de manera confiable directorios donde el nombre de un archivo contiene una nueva línea, pero eso rara vez se hace (recuerde esto como un posible problema de seguridad, no como un problema de usabilidad).

En python (tenga en cuenta que los metacaracteres de shell deben ser escapes remote_dir):

command_line = "echo ls -1 | sftp " + remote_site + ":" + remote_dir
remote_files = os.popen(command_line).read().split("\n")

Para interacciones más complejas, busque el modo por lotes de sftp en la documentación.

En algunos sistemas (Linux, Mac OS X, quizás otros unices, pero definitivamente no Windows), un enfoque diferente es montar un sistema de archivos remoto a través de ssh con sshfs , y luego trabajar localmente.


Estoy conectado a través de SSH a la máquina remota. No encontré ninguna manera de ejecutar una función de python como os.listdir en la máquina remota en una sola línea. Por lo tanto, esta pregunta. No quiero escribir un script para simplemente enumerar archivos. ¿Hay alguna forma de evitar este problema?
Fixxxer

@fixxxer: ssh cambia la situación, ¡es el tipo de cosas que deberías haber mencionado en tu pregunta original! Creo que sftp es apropiado para su caso de uso.
Gilles 'SO- deja de ser malvado'

Siento la confusión. ¿Hay alguna forma de insertar la contraseña en la "línea de comando" también?
Fixxxer

@fixxxer: No sé, los autores de ssh fruncen el ceño en las contraseñas almacenadas en texto sin formato y tienden a no hacerlo fácil. Realmente debería configurar la autenticación basada en claves (hay muchos tutoriales en la web y preguntas en superuser.com sobre esto).
Gilles 'SO- deja de ser malvado'

11

puedes usar ls -1

ls -l también hará el trabajo


La respuesta principal ya menciona las cosas exactas que dijiste. También la pregunta específicamente dice ls -lque no se debe utilizar.
DevX

2

Fácil, siempre que sus nombres de archivo no incluyan nuevas líneas:

find . -maxdepth 1

Si está transfiriendo esto a otro comando, probablemente debería preferir separar sus nombres de archivo por bytes nulos, en lugar de líneas nuevas, ya que los bytes nulos no pueden aparecer en un nombre de archivo (pero las líneas nuevas pueden):

find . -maxdepth 1 -print0

Imprimir eso en un terminal probablemente se mostrará como una línea, porque los bytes nulos normalmente no se imprimen. Algunos programas pueden necesitar una opción específica para manejar entradas delimitadas por nulos, como sort's -z. Su propia secuencia de comandos de manera similar tendría que dar cuenta de esto.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.