resueltos - scripts bash ejemplos
Listado solo directorios usando ls en bash: un examen (22)
Este comando lista los directorios en la ruta actual: ls -d */
¿Qué hace exactamente el patrón */
hacer?
¿Y cómo podemos dar la ruta absoluta en el comando anterior (por ejemplo, ls -d /home/alice/Documents
) para listar solo los directorios en esa ruta?
Solución real de ls
, incluyendo enlaces simbólicos a directorios.
Muchas respuestas aquí en realidad no usan ls
(o solo se usan en el sentido trivial de ls -d
, mientras que se usan comodines para la coincidencia del subdirectorio real. Una solución ls
verdadera es útil, ya que permite el uso de las opciones de ls
para el orden de clasificación , etc.
Excluyendo enlaces simbólicos
Se ha dado una solución que usa ls
, pero hace algo diferente de las otras soluciones en que excluye enlaces simbólicos a directorios:
ls -l | grep ''^d''
(posiblemente entubando sed
o awk
para aislar los nombres de los archivos)
Incluyendo enlaces simbólicos
En el caso (probablemente más común) de que deben incluirse enlaces simbólicos a directorios, podemos usar la opción -p
de ls
:
ls -1p | grep ''/$''
o, deshacerse de las barras inclinadas:
ls -1p | grep ''/$'' | sed ''s///$//''
Podemos agregar opciones a ls
según sea necesario (si se usa un listado largo, el -1
ya no es necesario).
nota: si queremos barras diagonales al final, pero no las queremos resaltadas con grep
, podemos eliminar el resaltado de forma hacker haciendo que la parte coincidente real de la línea esté vacía:
ls -1p | grep -P ''(?=/$)''
Cuatro formas de hacer esto, cada una con un formato de salida diferente
1. usando echo
Ejemplo: echo */
, echo */*/
Aquí está lo que tengo:
cs/ draft/ files/ hacks/ masters/ static/
cs/code/ files/images/ static/images/ static/stylesheets/
2. Usando solo ls
Ejemplo: ls -d */
Aquí es exactamente lo que tengo:
cs/ files/ masters/
draft/ hacks/ static/
O como lista (con información detallada): ls -dl */
3. Usando ls
y grep
Ejemplo: ls -l | grep "^d"
ls -l | grep "^d"
Esto es lo que obtuve:
drwxr-xr-x 24 h staff 816 Jun 8 10:55 cs
drwxr-xr-x 6 h staff 204 Jun 8 10:55 draft
drwxr-xr-x 9 h staff 306 Jun 8 10:55 files
drwxr-xr-x 2 h staff 68 Jun 9 13:19 hacks
drwxr-xr-x 6 h staff 204 Jun 8 10:55 masters
drwxr-xr-x 4 h staff 136 Jun 8 10:55 static
4. Bash Script (no recomendado para el nombre de archivo contiene espacio).
Ejemplo: for i in $(ls -d */); do echo ${i%%/}; done
for i in $(ls -d */); do echo ${i%%/}; done
Aquí está lo que tengo:
cs
draft
files
hacks
masters
static
Si te gusta tener ''/'' como carácter final, el comando será: for i in $(ls -d */); do echo ${i}; done
for i in $(ls -d */); do echo ${i}; done
cs/
draft/
files/
hacks/
masters/
static/
4 (más) opciones confiables.
Un asterisco no citado *
será interpretado como un patrón (glob) por el shell.
El shell lo usará en la expansión del nombre de ruta.
Entonces generará una lista de nombres de archivos que coinciden con el patrón.
Un simple asterisco coincidirá con todos los nombres de archivo en el PWD (directorio de trabajo actual).
Un patrón más complejo como */
coincidirá con todos los nombres de archivo que terminan en /
.
Así, todos los directorios. Es por eso que el comando:
1.- eco.
echo */
echo ./*/ ### avoid misinterpreting filenames like "-e dir"
será expandido (por el shell) para hacer echo
todos los directorios en el PWD.
Para probar esto: cree un directorio ( mkdir
) llamado como test-dir, y cd
en él:
mkdir test-dir; cd test-dir
Crea algunos directorios:
mkdir {cs,files,masters,draft,static} # safe directories.
mkdir {*,-,--,-v/ var,-h,-n,dir/ with/ spaces} # some a bit less secure.
touch -- ''file with spaces'' ''-a'' ''-l'' ''filename'' # and some files:
El comando echo ./*/
seguirá siendo confiable incluso con archivos con nombres impares:
./--/ ./-/ ./*/ ./cs/ ./dir with spaces/ ./draft/ ./files/ ./-h/
./masters/ ./-n/ ./static/ ./-v var/
Pero los espacios en los nombres de archivos hacen que la lectura sea un poco confusa.
Si en lugar de echo
, usamos ls
, el shell sigue siendo lo que está expandiendo la lista de nombres de archivos. El shell es la razón para obtener una lista de directorios en la PWD. La opción -d
a ls
hace que enumere la entrada del directorio actual en lugar de los contenidos de cada directorio (como se presenta de forma predeterminada).
ls -d */
Sin embargo, este comando es (algo) menos confiable. Se producirá un error con los archivos con nombres impares enumerados anteriormente. Se ahogará con varios nombres. Necesita borrar uno por uno hasta que encuentre los que tienen problemas.
2.- ls
El GNU ls
aceptará la tecla "fin de opciones" ( --
).
ls -d ./*/ ### more reliable BSD ls
ls -d -- */ ### more reliable GNU ls
3.-printf
Para listar cada directorio en su propia línea (en una columna, similar a ls -1), use:
$ printf "%s/n" */ ### Correct even with "-", spaces or newlines.
Y, aún mejor, podríamos eliminar el rastro /
:
$ set -- */; printf "%s/n" "${@%/}" ### Correct with spaces and newlines.
Un intento como este:
$ for i in $(ls -d */); do echo ${i%%/}; done
Fallará en
- algunos nombres (
ls -d */
) como ya se muestra arriba. - se verá afectado por el valor de
IFS
. - dividirá los nombres en espacios y tabulaciones (con
IFS
defecto). - Cada nueva línea en el nombre iniciará un nuevo comando de eco.
4.- Función
Finalmente, el uso de la lista de argumentos dentro de una función no afectará la lista de argumentos del shell actual en ejecución. Simplemente:
$ listdirs(){ set -- */; printf "%s/n" "${@%/}"; }
$ listdirs
presenta esta lista:
--
-
*
cs
dir with spaces
draft
files
-h
masters
-n
static
-v var
Estas opciones son seguras con varios tipos de nombres de archivos impares.
Acabo de agregar esto a mi archivo .bashrc
(también podría escribirlo en la línea de comandos si solo lo necesita / desea para una sesión)
alias lsd=''ls -ld */''
entonces lsd producirá el resultado deseado.
Agregando para completar el círculo, para recuperar la ruta de cada carpeta, usa una combinación de la respuesta de Albert y Gordans que deberían ser bastante útiles.
for i in $(ls -d /pathto/parent/folder/*/); do echo ${i%%/}; done
Salida:
/pathto/parent/folder/childfolder1/
/pathto/parent/folder/childfolder2/
/pathto/parent/folder/childfolder3/
/pathto/parent/folder/childfolder4/
/pathto/parent/folder/childfolder5/
/pathto/parent/folder/childfolder6/
/pathto/parent/folder/childfolder7/
/pathto/parent/folder/childfolder8/
El comando del tree
también es bastante útil aquí. Por defecto, mostrará todos los archivos y directorios a una profundidad completa, con algunos caracteres ASCII que muestran el árbol de directorios.
$ tree
.
├── config.dat
├── data
│ ├── data1.bin
│ ├── data2.inf
│ └── sql
| │ └── data3.sql
├── images
│ ├── background.jpg
│ ├── icon.gif
│ └── logo.jpg
├── program.exe
└── readme.txt
Pero si quisiéramos obtener solo los directorios, sin el árbol ascii, y con la ruta completa desde el directorio actual, podría hacer:
$ tree -dfi
.
./data
./data/sql
./images
Los argumentos son:
-d List directories only.
-f Prints the full path prefix for each file.
-i Makes tree not print the indentation lines, useful when used in conjunction with the -f option.
Y si luego desea la ruta absoluta, puede comenzar especificando la ruta completa al directorio actual:
$ tree -dfi "$(pwd)"
/home/alice/Documents
/home/alice/Documents/data
/home/alice/Documents/data/sql
/home/alice/Documents/images
Y para limitar el número de subdirectorios, puede establecer el nivel máximo de subdirectorios con -L level
, por ejemplo:
$ tree -dfi -L 1 "$(pwd)"
/home/alice/Documents
/home/alice/Documents/data
/home/alice/Documents/images
Se pueden ver más argumentos con el árbol del hombre.
En caso de que se esté preguntando por qué la salida de ''ls -d * /'' le da dos barras diagonales al final, como:
[prompt]$ ls -d */
app// cgi-bin// lib// pub//
probablemente se deba a que, en algún lugar, los archivos de configuración de la shell o de la sesión, alias el comando ls a una versión de ls que incluye el indicador -F. Ese indicador agrega un carácter a cada nombre de salida (que no es un archivo simple) que indica el tipo de cosa que es. Por lo tanto, una barra es la correspondiente al patrón ''* /'' y la otra barra es el indicador de tipo agregado.
Para deshacerse de este problema, podría, por supuesto, definir un alias diferente para ls. Sin embargo, para no invocar temporalmente el alias, puede anteponer el comando con barra invertida:
/ ls -d * /
Esto es lo que estoy usando
ls -d1 /Directory/Path/*;
Para listar solo directorios :
ls -l | grep ^d
para listar solo archivos :
ls -l | grep -v ^d
o también puedes hacer como: ls -ld * /
Para su información, si desea imprimir todos los archivos en multilínea, puede hacer un ls -1
que imprimirá cada archivo en una línea separada. archivo1 archivo2 archivo3
Para todas las carpetas sin subcarpetas:
find /home/alice/Documents -maxdepth 1 -type d
Para todas las carpetas con subcarpetas:
find /home/alice/Documents -type d
Probar si el elemento es un directorio con test -d
:
for i in $(ls); do test -d $i && echo $i ; done
Prueba este. esto funcionará en todas las distribuciones ls -ltr | grep drw
Resolví parcialmente con:
cd "/path/to/pricipal/folder"
for i in $(ls -d .*/); do sudo ln -s "$PWD"/${i%%/} /home/inukaze/${i%%/}; done
ln: «/home/inukaze/./.»: can''t overwrite a directory
ln: «/home/inukaze/../..»: can''t overwrite a directory
ln: accesing to «/home/inukaze/.config»: too much symbolics links levels
ln: accesing to «/home/inukaze/.disruptive»: too much symbolics links levels
ln: accesing to «/home/inukaze/innovations»: too much symbolics links levels
ln: accesing to «/home/inukaze/sarl»: too much symbolics links levels
ln: accesing to «/home/inukaze/.e_old»: too much symbolics links levels
ln: accesing to «/home/inukaze/.gnome2_private»: too much symbolics links levels
ln: accesing to «/home/inukaze/.gvfs»: too much symbolics links levels
ln: accesing to «/home/inukaze/.kde»: too much symbolics links levels
ln: accesing to «/home/inukaze/.local»: too much symbolics links levels
ln: accesing to «/home/inukaze/.xVideoServiceThief»: too much symbolics links levels
Bueno, esto me redujo, la parte mayor :)
Si el directorio oculto no es necesario para ser listado, ofrezco:
ls -l | grep "^d" | awk -F" " ''{print $9}''
Y si se necesitan listados directorios ocultos, use:
ls -Al | grep "^d" | awk -F" " ''{print $9}''
O
find -maxdepth 1 -type d | awk -F"./" ''{print $2}''
Una sola línea para listar directorios solo desde "aquí".
Con el recuento de archivos.
for i in `ls -d */`; do g=`find ./$i -type f -print| wc -l`; echo "Directory $i contains $g files."; done
Utilizando Perl:
ls | perl -nle ''print if -d;''
Yo suelo:
ls -d */ | cut -f1 -d''/''
Esto crea una sola columna sin barra diagonal final, útil en los scripts.
Mis dos centavos.
para mostrar listas de carpetas sin /
ls -d */|sed ''s|[/]||g''
*/
es un patrón de coincidencia de nombre de archivo que coincide con los directorios en el directorio actual.
Para listar solo los directorios, me gusta esta función:
# long list only directories
llod () {
ls -l --color=always "$@" | grep --color=never ''^d''
}
Ponlo en tu .bashrc.
Ejemplos de uso:
llod # long listing of all directories in current directory
llod -tr # same but in chronological order oldest first
llod -d a* # limit to directories beginning with letter ''a''
llod -d .* # limit to hidden directories
NOTA: se romperá si usas la opción -i
. Aquí hay una solución para eso:
# long list only directories
llod () {
ls -l --color=always "$@" | egrep --color=never ''^d|^[[:digit:]]+ d''
}
*/
es un patrón que coincide con todos los subdirectorios en el directorio actual ( *
coincidiría con todos los archivos y subdirectorios; el /
restringe a directorios). De manera similar, para enumerar todos los subdirectorios bajo / home / alice / Documents, use ls -d /home/alice/Documents/*/
file *|grep directory
O / P (En mi máquina) -
[root@rhel6 ~]# file *|grep directory
mongo-example-master: directory
nostarch: directory
scriptzz: directory
splunk: directory
testdir: directory
Por encima de la salida se puede refinar más utilizando corte.
file *|grep directory|cut -d'':'' -f1
mongo-example-master
nostarch
scriptzz
splunk
testdir
* could be replaced with any path that''s permitted
file - determine file type
grep - searches for string named directory
-d - to specify a field delimiter
-f1 - denotes field 1