Meu roteiro:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
E aqui está o erro:
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
O que estou fazendo de errado?
Responder1
Seu código original antes das edições:
#!/bin/sh
_directory1="~/test1"
_directory2="test2"
for i in $(cd "${_directory1}/$_directory2")
do
echo "$i"
done
O til(
~
) não se comporta como uma variável. Ele não será, por exemplo, expandido para o caminho do seu diretório inicial quando usado entre aspas. Em um script, use$HOME
em vez de til.~
é um "atalho" que você pode usar na linha de comando, mas$HOME
é mais descritivo em um script.- Ver "Por que o til (~) não se expande entre aspas duplas?" Para maiores informações.
cd
não produz nada que você possa fazer um loop, portanto, usarcd
uma substituição de comando comfor
não fará nada de bom. Infelizmente, não está claro o que você deseja que seu loop realmente faça, então não posso fornecer uma implementação alternativa infalível.
O código com suas edições:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
Este código só geraria
"./myscript.sh: 6: cd: can't cd to /test2"
se você digitar incorretamente o nome da variável _directory1
(e a variável incorreta estiver vazia e o /test2
diretório não existir).
Você então editou a mensagem de errode novodizer que isso produz
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
o que significa simplesmente que o diretório /home/user/test1/test2
não existe. Você não forneceu evidências de que este diretóriofazexistem, então temos que acreditar na palavra do seu sistema quanto a isso.
Aqui está um script que lista o conteúdo de um diretório (assumindo que o diretório existe). O código imprime o nome do caminho completo de cada arquivo.
#!/bin/bash
topdir=$HOME/test1
subdir=test2
printf '%s\n' "$topdir/$subdir"/*
Ou,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$name"
done
A nullglob
opção shell faz com que o loop não seja executado se o padrão fornecido não corresponder a nada. Sem definir a nullglob
opção, o padrão permaneceria sem expansão se não correspondesse a nada, e o loop o usaria como valor $name
em uma única iteração.
Você também pode querer definir a dotglob
opção shell ( shopt -s dotglob
) se estiver interessado em nomes ocultos (nomes de arquivos começando com um .
caractere).
Ou, sem imprimir o caminho completo para cada nome de arquivo,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
printf '%s\n' *
O exit 1
encerrará o script se cd
falhar.
Ou,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
shopt -s nullglob
for name in *; do
printf '%s\n' "$name"
done
Para imprimir apenas os nomes dos arquivos sem o caminho completo, sem usar cd
:
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$( basename "$name" )"
# or: printf '%s\n' "${name##*/}"
done
Isso usa o basename
utilitário para extrair apenas a parte do nome do arquivo dos nomes de caminho. A alternativa no comentário usa uma substituição de parâmetro padrão, ${name##*/}
para excluir o caminho do diretório inicial antes dos nomes dos arquivos (literalmente "remover a string de prefixo mais longa que corresponda ao padrão */
de $name
").