En una Mac, ¿cómo puedo enumerar el contenido de un directorio no actual sin mostrar archivos de respaldo (que terminan en ~), preferiblemente con el comando BSD ls?

En una Mac, ¿cómo puedo enumerar el contenido de un directorio no actual sin mostrar archivos de respaldo (que terminan en ~), preferiblemente con el comando BSD ls?

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 lsproporciona 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, lsnaturalmente realiza esta tarea cuando el directorio no actual se usa como argumento para ls: ls argdónde arges una ruta absoluta o relativa al directorio no actual (como /absolute/path/to/directory, ~/path/from/home/to/directoryo 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 -dopció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 arges 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 lsmostrar 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 -Bopció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 grepcambia 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 lsen una subshell:

(cd arg; ls -d *[^~])

Respuesta2

Usando bashy su GLOBIGNOREvariable 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 GLOBIGNOREuna lista de :patrones delimitados hará que la finalización del nombre de archivo ignore esos patrones.

La basenameutilidad en macOS acepta más de un nombre de ruta si usa su -aopció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 -Bcomo 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 lssin 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_TYPEy 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 lsy lse establecen .bashrccon la primera definición LS_TYPEy elección de qué archivo de configuración obtener, por ejemplo:

LS_TYPE="BSD"
source ~/.config/bash/bashrc_aliases_lsBSD

información relacionada