Mi sistema:
- Sistema operativo: MacOS/Mac OS X (Mojave 10.14.5)
- Núcleo del sistema operativo: Darwin (18.6.0)
- Núcleo: Núcleo Darwin / XNU (18.6.0 / xnu-4903.261.4~2/RELEASE_X86_64)
- ls: versión desconocida, pero
man ls
proporciona una página del Manual de comandos generales de BSD - Conchas:
- Bash: GNU bash, versión 5.0.7(1) (x86_64-apple-darwin18.5.0)
- Zsh: zsh 5.7.1 (x86_64-apple-darwin18.2.0)
En MacOS, en una CLI de terminal que usa un shell como bash o zsh, me gustaría usar el comando (BSD) ls
(o quizás una herramienta común y útil similar) para enumerar el contenido de un directorio que no sea el directorio de trabajo actual. , donde ~
se muestran todos los archivos excepto aquellos que terminan con tilde ( ).
Excluyendo la última estipulación, ls
naturalmente realiza esta tarea cuando el directorio no actual se usa como argumento para ls
: ls arg
dónde arg
es una ruta absoluta o relativa al directorio no actual (como /absolute/path/to/directory
, ~/path/from/home/to/directory
o path/from/current/dir/to/directory
).
Sé cómo enumerar contenidos que no son de respaldo en el directorio actual, usando la expansión de nombre de archivo (también conocida como "globbing") y la -d
opción (para enumerar directorios y no sus contenidos), así: ls -d *[^~]
(o ls -d *[!~]
). Quiero el mismo tipo de resultados, pero para un directorio no actual.
Casi puedo lograr lo que quiero usando ls -d arg/*[^~]
, donde arg
es lo mismo que se describió anteriormente, pero los resultados muestran la ruta a cada elemento de contenido (es decir, cada archivo y directorio en el directorio de interés). Quiero ls
mostrar cada elemento sin la ruta al mismo, como se hace con ls arg
.
En Linux, usando el comando GNU ls
, puedo lograr exactamente lo que quiero usando la -B
opción de no enumerar los archivos de respaldo: ls -B arg
. Aunque esto es lo que quiero, me gustaría lograrlo utilizando herramientas nativas de MacOS, preferiblemente BSD ls
.
Nota: No quiero usar grep
(por ejemplo, ls arg | grep '.*[^~]$'
), porque grep
cambia el formato y el color de la salida.
Resumen de la pregunta: en una Mac, ¿cómo puedo enumerar el contenido de un directorio no actual pero no los archivos de respaldo, preferiblemente usando ls
?
Respuesta1
Podrías ejecutar ls
en una subshell:
(cd arg; ls -d *[^~])
Respuesta2
Usando bash
y su GLOBIGNORE
variable de shell, junto con macOS basename
:
$ mkdir dir
$ touch dir/file{1,2}{,~}
$ ls -R
dir
./dir:
file1 file1~ file2 file2~
$ GLOBIGNORE=*~
$ ls -d dir/*
dir/file1 dir/file2
$ basename -a dir/*
file1
file2
Configurar GLOBIGNORE
una lista de :
patrones delimitados hará que la finalización del nombre de archivo ignore esos patrones.
La basename
utilidad en macOS acepta más de un nombre de ruta si usa su -a
opción y devolverá una lista que consta solo de las partes del nombre de archivo de esos nombres de ruta.
En lugar de usar GLOBIGNORE
(que proporciona una forma más genérica de ignorar ciertas expansiones de patrones de nombres de archivos), obviamente podría usar su patrón *[!~]
(tenga en cuenta que !
niega una clase de carácter en el shell, mientras que ^
niega una clase de carácter en expresiones regulares):
unset GLOBIGNORE
basename -a dir/*[!~]
... o simplemente puede instalar GNU coreutils desde Homebrew y usarlo gls -B
como está acostumbrado en sistemas Linux.
Respuesta3
La respuesta concisa es usar un subshell para ejecutar el comando en el directorio no actual:
(cd arg; ls -d *[^~])
Pero para crear una función general que funcione tanto para el directorio actual como para cualquier directorio no actual, podemos agregar lo siguiente a .bashrc
(o a bashrc_aliases_lsBSD
, obtenido de .bashrc
):
alias ls='/bin/ls'
alias l=''
unalias l
function l () { ( if [[ -n "$@" ]]; then cd "$@"; fi ; /bin/ls -d *[^~] ) }
Si desafiamos la preferencia mencionada anteriormente por usar BSD, podemos usar GNU ls
sin ningún problema instalando las utilidades principales de GNU (por ejemplo, a través de brew install coreutils
) y creando los alias deseados (en lugar de usar el código anterior) en .bashrc
(o en bashrc_aliases_lsGNU
, obtenido por .bashrc
) :
alias ls='/usr/local/bin/gls'
alias l='/usr/local/bin/gls -B'
Mi propia solución actual es usar ambas construcciones y cambiar entre ellas cuando lo desee usando una variable que llamo LS_TYPE
y una función que llamo ls-switch
(definida en bashrc_aliases
, obtenida por .bashrc
), que genera uno de los dos archivos de configuración que contienen estas dos construcciones:
function ls-switch () {
if [[ $LS_TYPE = "GNU" ]] ; then
LS_TYPE="BSD"
source ~/.config/bash/bashrc_aliases_lsBSD
elif [[ $LS_TYPE = "BSD" ]] ; then
LS_TYPE="GNU"
source ~/.config/bash/bashrc_aliases_lsGNU
fi
}
Con esta disposición, los comportamientos predeterminados de ls
y l
se establecen .bashrc
con la primera definición LS_TYPE
y elección de qué archivo de configuración obtener, por ejemplo:
LS_TYPE="BSD"
source ~/.config/bash/bashrc_aliases_lsBSD