
function mv1 { mv -n "$1" "targetdir" -v |wc -l ;}
mv1 *.png
Ele move apenas o primeiro .png
arquivo que encontra, não todos eles.
Como posso aplicar o comando a todos os arquivos que correspondem aos curingas?
Responder1
mv1 *.png
primeiro expande o padrão curinga *.png
na lista de nomes de arquivos correspondentes e, em seguida, passa essa lista de nomes de arquivos para a função.
Então, dentro da função $1
significa: pegar o primeiro argumento da função, dividi-lo onde ele contém espaços em branco e substituir qualquer uma das partes separadas por espaços em branco que contenham caracteres curinga e correspondam a pelo menos um nome de arquivo pela lista de nomes de arquivos correspondentes. Parece complicado? É, e esse comportamento só é útil ocasionalmente e costuma ser problemático. Esse comportamento de divisão e correspondência ocorre apenas se $1
ocorrer fora das aspas duplas, portanto a correção é fácil: use aspas duplas.Sempre coloque aspas duplas nas substituições de variáveisa menos que você tenha um bom motivo para não fazê-lo.
Por exemplo, se o diretório atual contém os dois arquivos A* algorithm.png
e graph1.png
, então mv1 *.png
passa A* algorithm.png
como o primeiro argumento para a função e graph1.png
como o segundo argumento. Então $1
é dividido em A*
e algorithm.png
. O padrão A*
corresponde A* algorithm.png
e algorithm.png
não contém caracteres curinga. Então a função acaba rodando mv
com os argumentos -n
, A* algorithm.png
, algorithm.png
, targetdir
e -v
. Se você corrigir a função para
function mv1 { mv -n "$1" "targetdir" -v |wc -l ;}
então ele moverá corretamente o primeiro arquivo.
Para processartodosos argumentos, diga ao shell para processar todos os argumentos e não apenas o primeiro. Você pode usar "$@"
para significar a lista completa de argumentos passados para a função.
function mv1 { mv -n "$@" "targetdir" -v |wc -l ;}
Isso está quase correto, mas ainda falhará se um nome de arquivo começar com o caractere -
, porque mv
tratará esse argumento como uma opção. Passe --
para mv
para dizer “não há mais opções após este ponto”. Esta é uma convenção muito comum que a maioria dos comandos suporta.
function mv1 { mv -n -v -- "$@" "targetdir" |wc -l ;}
Um problema remanescente é que, se mv
falhar, esta função retornará um status de sucesso, porque o status de saída dos comandos no lado esquerdo de um canal é ignorado. No bash (ou ksh), você pode usar set -o pipefail
para fazer o pipeline falhar. Observe que definir esta opção pode causar falha em outro código executado no mesmo shell, portanto, você deve configurá-la localmente na função, o que é possível desde o bash 4.4.
function mv1 {
local -
set -o pipefail
mv -n -v -- "$@" "targetdir" | wc -l
}
Nas versões anteriores, a configuração pipefail
seria frágil, então seria melhor verificar PIPESTATUS
explicitamente.
function mv1 {
mv -n -v -- "$@" "targetdir" | wc -l
((!${PIPESTATUS[0] && !${PIPESTATUS[1]}}))
}
Responder2
$1
é o primeiro argumento da função, aqui o primeiro arquivo que corresponde a *.png
. Eu acho que "$@"
é isso que você deseja usar em vez de $1
.
Responder3
Você teria que usar mv1 \*.png
.
Ao interagir com funções, o Terminal Linux não passa o asterisco diretamente para o comando, mas seleciona o primeiro parâmetro correspondente e passa-o para o comando.
Para permitir que o asterisco passe diretamente, é necessário escapar do asterisco usando uma barra invertida.