Sim, é possível implementar a conclusão do caminho a partir de um diretório base personalizado especificado por um sinalizador de opção de linha de comando. Aqui está um pequeno exemplo ilustrando como conseguir isso. Primeiro, vou modificar um pouco seu script de exemplo para tornar a demonstração um pouco mais interessante (ou seja, produzir saída):
#!/bin/bash
# echo_path.sh
#
# Echoes a path.
#
# Parse command-line options
while getopts ":d:" opt; do
# Use '-d' to specify relative path
case "${opt}" in
d)
directory="${OPTARG}"
;;
esac
done
# Print the full path
echo "$(readlink -f ${directory})"
Isto é essencialmente o mesmo que o seu script de exemplo, mas imprime o argumento dado.
Em seguida, precisamos escrever uma função a ser chamada pelo sistema de conclusão programática Bash. Aqui está um script que define essa função:
# echo_path_completion.bash
# Programmatic path completion for user specified file paths.
# Define a base directory for relative paths.
export BASE_DIRECTORY=/tmp/basedir
# Define the completion function
function _echo_path_completion() {
# Define local variables to store adjacent pairs of arguments
local prev_arg;
local curr_arg;
# If there are at least two arguments then we have a candidate
# for path-completion, i.e. we need the option flag '-d' and
# the path string that follows it.
if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
# Get the current and previous arguments from the command-line
prev_arg="${COMP_WORDS[COMP_CWORD-1]}";
curr_arg="${COMP_WORDS[COMP_CWORD]}";
# We only want to do our custom path-completion if the previous
# argument is the '-d' option flag
if [[ "${prev_arg}" = "-d" ]]; then
# We only want to do our custom path-completion if a base
# directory is defined and the argument is a relative path
if [[ -n "${BASE_DIRECTORY}" && ${curr_arg} != /* ]]; then
# Generate the list of path-completions starting from BASE_DIRECTORY
COMPREPLY=( $(compgen -d -o default -- "${BASE_DIRECTORY}/${curr_arg}") );
# Don't append a space after the command-completion
# This is so we can continue to apply completion to subdirectories
compopt -o nospace;
# Return immediately
return 0;
fi
fi
fi
# If no '-d' flag is given or no base directory is defined then apply default command-completion
COMPREPLY=( $(compgen -o default -- "${curr_arg}") );
return 0;
}
# Activate the completion function
complete -F _echo_path_completion echo_path
Agora vamos criar nosso script de conclusão:
source echo_path_completion.bash
Vamos tornar nosso script executável e movê-lo para algum lugar em nosso PATH:
chmod +x echo_path.bash
mv -i echo_path.bash /usr/local/bin
E, finalmente, vamos adicionar um alias ao nosso script que não tenha uma extensão de arquivo:
alias echo_path=echo_path.bash
Agora, se você inserir echo -d
e clicar no botão da guia, deverá obter a conclusão do caminho do arquivo a partir do BASE_DIRECTORY. Para testar isso, você pode tentar o seguinte:
mkdir -p ${BASE_DIRECTORY}
mkdir -p "${BASE_DIRECTORY}/file"{1..5}
Ao clicar na guia, você deve obter a seguinte lista de conclusões:
user@host:~$ echo_path -d
user@host:~$ echo_path -d /tmp/basedir/file
/tmp/basedir/file1 /tmp/basedir/file2 /tmp/basedir/file3 /tmp/basedir/file4 /tmp/basedir/file5
Observe que, após a primeira guia, a string é convertida em um caminho absoluto. Você pode mudar isso se quiser, mas acho que esse é o comportamento preferível.
Aqui estão algumas referências que você pode consultar para mais informações.
Para referências oficiais, dê uma olhada nas seguintes seções do manual de Bash:
-
Seção: 5.2 Variáveis de Bash ( procure variáveis com o prefixo
COMP_
)
Veja também o Advanced Bash Scripting Guide do Projeto de Documentação do Linux:
Para uma rápida introdução a alguns recursos de conclusão programática no Bash, veja este post no site "The Geek Stuff":
Também há várias postagens relacionadas ao StackOverflow que você pode achar úteis: