Expansión de Tilde entre comillas

Escribo un script donde debo encontrar algunos archivos en un directorio definido por el usuario que puede contener tilde (por lo tanto, es posible tener user_defined_directory='~/foo' ). La construcción se ve como

 found_files=$(find "$user_defined_directory" -type f … ) 

Utilizo comillas para cubrir posibles espacios en esa ruta, pero la expansión de tilde no funciona entre comillas según la página de manual. Sé acerca de : operador que probablemente pueda hacer esta expansión, pero no puedo encontrar la forma de usarlo aquí.

El ‘directorio definido por el usuario’ se toma de otro archivo de configuración en el directorio $ HOME del usuario. No está pasando a mi script como un parámetro, sino que está siendo analizado a partir de esa otra configuración en el script que escribo.

Puede usar "${user_defined_directory/#~/$HOME}" para reemplazar un “~” al comienzo de la cadena con el directorio de inicio del usuario actual. Tenga en cuenta que esto no manejará el formato ~username/subdir , solo un simple ~ . Si necesita manejar las versiones más complejas, necesitará escribir un conversor mucho más complejo.

Esto funciona con algunas suposiciones bastante verosímiles, pero está lejos de ser un código obvio (y tampoco es de una sola línea):

 # Working function - painful, but can you simplify any of it? # NB: Assumes that ~user does not expand to a name with double spaces or # tabs or newlines, etc. expand_tilde() { case "$1" in (\~) echo "$HOME";; (\~/*) echo "$HOME/${1#\~/}";; (\~[^/]*/*) local user=$(eval echo ${1%%/*}) echo "$user/${1#*/}";; (\~[^/]*) eval echo ${1};; (*) echo "$1";; esac } # Test cases name1="~/Documents/over enthusiastic" name2="~crl/Documents/double spaced" name3="/work/whiffle/two spaces are better than one" expand_tilde "$name1" expand_tilde "$name2" expand_tilde "$name3" expand_tilde "~" expand_tilde "~/" expand_tilde "~crl" expand_tilde "~crl/" # This is illustrative of the 'normal use' of expand_tilde function x=$(expand_tilde "$name1") echo "x=[$x]" 

Cuando se ejecuta en mi máquina (donde hay un usuario crl ), la salida es:

 /Users/jleffler/Documents/over enthusiastic /Users/crl/Documents/double spaced /work/whiffle/two spaces are better than one /Users/jleffler /Users/jleffler/ /Users/crl /Users/crl/ x=[/Users/jleffler/Documents/over enthusiastic] 

La función tilde_expansion trata los diferentes casos por separado y de manera diferente. La primera cláusula trata sobre un valor ~ y simplemente sustituye $HOME . El segundo es un caso de paranoia: ~/ está mapeado a $HOME/ . El tercero trata de ~/anything (incluido un “nada” vacío). El siguiente caso trata de ~user . El catch-all * ocupa de todo lo demás.

Tenga en cuenta que el código hace la suposición (plausible) de que ~user no se expandirá a un valor que contenga espacios dobles, ni tabs o líneas nuevas (y posiblemente otros caracteres espaciales). Si tienes que lidiar con eso, la vida será un infierno.

Tenga en cuenta la respuesta a chdir() al directorio de inicio , lo que explica que POSIX requiere ~ expandirse al valor actual de $HOME , pero ~user expande al valor del directorio de inicio desde la base de datos de contraseñas.

Tilde definitivamente no se expande dentro de la cita. Puede haber algún otro truco de bash, pero lo que hago en esta situación es este:

 find ~/"$user_defined_directory" -type f 

es decir, mueve el inicio ~/ fuera de las comillas y conserva el rest de la ruta en las comillas.