it-swarm-es.com

Alternar la redirección de Bash con una variable

MUTE='&> /dev/null'
echo "text" $MUTE

¿Hay alguna manera de hacer que ese trabajo mantenga la redirección dentro de la variable?

4
Julen Larrucea

En mi humilde opinión, sería más elegante usar la presencia/valor de la variable para cerrar condicionalmente los descriptores de archivo, p.

$ cat myscript.sh
#!/bin/bash

if [ -n "$MUTE" ]; then
    exec &>-
fi

echo somestuff
echo someerr >&2

entonces

$ ./myscript.sh
somestuff
someerr

pero

$ MUTE=yes ./myscript.sh
$

Si realmente desea alternar la redirección, podría considerar crear una función Shell que duplique los descriptores del archivo antes de cerrarlos, y luego restaure los duplicados para volver a habilitar las transmisiones originales, p.

#!/bin/bash

function mute {
  case "$1" in
    "on") 
      exec 3>&1-
      exec 4>&2-
    ;;
    "off") 
      exec 1>&3-
      exec 2>&4-
    ;;
    *)
  esac
}


# Demonstration: 

echo "with mute on: "
mute on
ls somefile
ls nofile

mute off
echo "with mute off: "
ls somefile
ls nofile

Resultado:

$ ./mute.sh
with mute on: 
with mute off: 
somefile
ls: cannot access nofile: No such file or directory
4
steeldriver

De Manual de referencia de Bash: Expansión de comando simple :

  1. Las palabras que el analizador ha marcado como asignaciones variables (las que preceden al nombre del comando) y las redirecciones se guardan para su posterior procesamiento.
  2. Las palabras que no son asignaciones variables o redirecciones se expanden (ver Expansiones de Shell). Si quedan palabras después de la expansión, se considera que la primera palabra es el nombre del comando y las palabras restantes son los argumentos.
  3. Las redirecciones se realizan como se describe anteriormente (ver Redirecciones).

Esto significa que el analizador de comandos primero identifica todas las redirecciones, luego realiza las diversas expansiones y finalmente resuelve las redirecciones que identificó previamente : esas no incluyen posibles redirecciones resultantes de las expansiones.

Sin embargo de help eval:

Execute arguments as a Shell command.

    Combine ARGs into a single string, use the result as input to the Shell,
    and execute the resulting commands.

Entonces, usando eval podría crear una especie de nivel de indirección que permitirá que el comando se procese dos veces:

MUTE='&> /dev/null'
eval echo "text" $MUTE
$ MUTE='&> file'
$ eval echo "text" $MUTE
$ cat file
text
3
kos

Se podría usar una función que escriba su stdin donde lo desee.

$> MUTE(){  cat /dev/stdin > testFile.txt  ; }                                                    
$> df | MUTE                                                                                      
$> cat testFile.txt
Filesystem     1K-blocks     Used Available Use% Mounted on
udev             1954208        4   1954204   1% /dev
tmpfs             393160     3548    389612   1% /run
/dev/sda1      115247656 95511252  13859056  88% /
none                   4        0         4   0% /sys/fs/cgroup
none                5120        0      5120   0% /run/lock
none             1965792      872   1964920   1% /run/shm
none              102400      128    102272   1% /run/user
cgmfs                100        0       100   0% /run/cgmanager/fs

O podríamos decirle a la función que ejecute lo que queramos con redirección

$> MUTE(){  "[email protected]" > testFile.txt  ; }                                                              
$> MUTE lsblk                                                                                     
$> cat testFile.txt                                                                               
NAME                             MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda                                8:0    0 111.8G  0 disk 
└─sda1                             8:1    0 111.8G  0 part /

Manera no estándar, piratería, pero funciona :)

2

Funciona de esta manera, no sé si es utilizable para su enfoque:

MUTE='&> /dev/null'
bash -c "echo \"text\" $MUTE"
1
cmks