adiciona opção de caminho absoluto a um comando

2

Dado um comando shell (vamos chamá-lo de "oldcommand"), existe um script de shell simples newcommand.sh que se comportará como oldcommand, exceto que ele terá uma nova opção "-location" e, por exemplo,

  newcommand -location path -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4

executará

 oldcommand  -nonfileoption1 x1 -fileoption2 path/x2 -fileoption3 path/x3  -nonfileoption4 x4
    
por Ewan Delanoy 02.12.2015 / 10:39

3 respostas

2

Isso cheira muito a um problema XY . Se você quiser que oldcommand trate todos os nomes de arquivos relativos em relação a um diretório diferente, altere o diretório atual!

(cd path && oldcommand  -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4)

Os parênteses asseguram que a mudança do diretório é local: o próximo comando será executado no diretório original.

Se você quiser empacotar isso em um script:

#!/bin/sh
cd "$1" && shift && "$@"

Uso:

run-in path oldcommand  -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4

Para uso de linha de comando, no entanto, uma alteração de diretório temporário pode ser mais conveniente. Requer um pouquinho mais de digitação, mas permite que a finalização do nome do arquivo funcione fora da caixa. (Você pode fazer o trabalho de conclusão do método de script de wrapper, mas precisará definir uma função de conclusão para o script run-in .)

cd path
oldcommand  -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4
cd -

ou

pushd path
oldcommand  -nonfileoption1 x1 -fileoption2 x2 -fileoption3 x3  -nonfileoption4 x4
popd

Comparado ao que você está perguntando, isso faz com que todos os nomes de arquivos relativos sejam relativos a path , não apenas aqueles transmitidos na linha de comando, mas qualquer nome de arquivo relativo que oldcommand use internamente. Isso também pressupõe que oldcommand não mude para um diretório diferente. Ambas as suposições são atendidas por muitos comandos.

    
por 03.12.2015 / 00:05
4

Se tudo de que você gosta é uma opção no começo, são algumas linhas de script. Analisar a opção em um local arbitrário e passá-la ao oldcommand requer várias linhas e algum conhecimento sobre quais opções têm valores e quais não possuem.

Para o caso simples ,

#!/bin/sh
[ "$#" -gt 2 && "x$1" = "x-location" ] && cd $2 && shift 2 && exec oldcommand "$@"
newcommand "$@"

Para o caso complicado, isso soa como algo que você poderia fazer com getopt (não portátil). Leitura adicional:

Por discussão com OP, aqui está o padrão que pode ser usado para simplificar o problema: as opções que começam com "'-fileopt" devem ter o valor da opção de localização prefixado. Então (sem verificação de erros reais, e não realmente manipulando caracteres especiais incorporados nos nomes de caminho):

#!/bin/sh
PREP=
if [ "$#" -gt 2 ]
then
    PREP="$2/"
    shift 2
    ARGS=
    while [ "$#" != 0 ]
    do
        case "x$1" in
        (x-fileopt*)
            ARGS="$ARGS $1 ${PREP}$2"
            shift 2
            ;;
        (*)
            ARGS="$ARGS $1"
            shift 1
        esac
    done
    oldcommand $ARGS
else
    oldcommand "$@"
fi
    
por 02.12.2015 / 10:48
1
opt()
    case ${1##*:*}:${#2} in
    (--:*) ! x=$((x-2))  ;;
    (-nonfileoption:[!0]*) p=;;
    (-fileoption:[!0]*)    p=\/;;
    (*:0)  eval $"{$x"':?Bad option::arg: "$1::$2"}';;
    (*)    eval $"{$((x-1))"':?Bad option: "$1"}'
    esac

[ " -location" = " $1" ] && x=2 parm= &&
while  [ "$#" -ge "$((x+=2))" ]
do     eval 'opt  "${'"$((x-1))"'}" "${'"$x}\"" ||
          until [ "$x" -eq "$#" ] && break 2
          do    parm=$parm' "${'$((x+=1))}\"
          done
       parm=$parm' "${'$((x-1))'}"  "'$p\${$x}\"
done&& eval "set -- $parm"
    
por 02.12.2015 / 14:40