
Recebo o seguinte erro quando executo o script a seguir:
cp: cannot stat ls
Conteúdo do roteiro
#!/bin/bash
#make copies of all files in directory
cd /home/don
LIST='ls'
for i in $LIST; do
ORIG=$i
DEST=$i.old
cp $ORIG $DEST
echo "Copied $i"
done
Alguém pode ver o problema?
Responder1
Um dos principais erros é que você está tentando usar o ls
comando, mas a variável LIST contém apenas a string 'ls'. Você pode usar a substituição de comandos com a $(command)
sintaxe. Eu desaconselho isso neste caso, pois não fornecerá informações em um formato que você possa usar facilmente. Quase sempre é umerro ao analisar a saída dels
.
Nesta circunstância você deve usar a correspondência de padrões de shell, também conhecida comoglobulando.
Eu sugeriria o seguinte método em seu script:
#!/bin/bash
#make copies of all files in directory
for i in /home/don/* ; do
if [[ -f $i ]]; then
orig="$i"
dest="${i}.old"
cp "$orig" "$dest"
echo "Copied $i"
else
echo "${i} is not a file"
fi
done
- Isso usa shell globbing para corresponder a todos os arquivos no diretório.
./*
significa tudo no diretório atual (.
). - A
if
instrução verifica se a correspondência é um arquivo (falhará em diretórios e links) e faz sua sequência de cópia, se for. - Alterei os nomes das variáveis para letras minúsculas, pois as variáveis de ambiente do sistema estão em letras maiúsculas, para evitar conflitos de nomes indesejados.
Responder2
Bem, há um pequeno erro no seu script. Na quarta linha você pretendia executareuportanto, não deve estar entre aspas simples, mas deve ser colocado dentro do símbolo``. Então seu script muda da seguinte maneira
LIST=`ls`
Tente atualizar seu script conforme acima.
No entanto, é aconselhável não usar $(ls)
nada, você deve preferir globbing de shell no cabeçalho do loop.
for i in *; do
ComoSr. David Anderssoncomentei abaixo que isso poderia ser usado com aspas para valores de variáveis ("$eu") para as instruções seguintes, caso contrário, poderá haver problemas com espaços nos nomes de arquivos. Você pode evitar isso usando find combinado com substituição de processo:
while read l; do
i=$(basename "$l")
done < <(find . -name '*' -maxdepth 1)
Uma resposta detalhada com roteiro e explicação é fornecida abaixo porSr. Arronical. Por favor, consulte-o para melhores scripts no futuro.
Responder3
A versão do comando 'encontrar'
Seu script pode ser feito como um find
comando de uma linha, sem a necessidade de analisar ls
ou mexer com globs , etc.
Seu objetivo, até onde diz a pergunta, é fazer cópias de todos os arquivos no diretório atual. Para isso, o comando apropriado seria:
find . -maxdepth 1 -mindepth 1 -exec cp {} {}".old" \;
O que isso faz é find
operar em todos os arquivos do .
diretório (atual) e chamar cp
por cada arquivo (portanto \;
). Por find
ser recursivo, temos que limitar a profundidade da pesquisa, portanto, -maxdepth
sinalizar e -mindepth
sinalizar é evitar a listagem .
como um dos resultados da pesquisa.
Execução de amostra:
$ touch "file one" "file two"
$ find . -maxdepth 1 -mindepth 1 -exec cp {} {}".old" \;
$ ls -1
file one
file one.old
file two
file two.old
$
OBSERVAÇÃO: cp
ainda reclamará dos diretórios. Existem algumas maneiras de lidar com isso.
1) você pode filtrar apenas arquivos se esse for seu objetivo com -type f
sinalizador find
como
find . -mindepth 1 -maxdepth 1 -type f -exec cp {} {}".old" \;
2) Use cp -r
também para fazer cópias de diretórios
find . -mindepth 1 -maxdepth 1 -exec cp -r {} {}".old" \;
Linha única do Python
É um pouco mais longo que find
o anterior, mas ainda dá conta do recado e não tem problemas com nomes de arquivos especiais.
python -c 'import shutil; import os;[shutil.copyfile(f,f + ".old") for f in os.listdir(".") if os.path.isfile("./" + f)]'
Execução de amostra:
$ touch "test file 1" "testfile 2"
$ python -c 'import shutil;import os;[shutil.copyfile(f,f + ".old")
> for f in os.listdir(".")
> if os.path.isfile("./" + f)]'
$ ls -1
test file 1
test file 1.old
testfile 2
testfile 2.old
$
Para incluir diretórios, useshutil.copytree(source,destination)
python -c 'import shutil; import os;[shutil.copyfile(f,f + ".old") if os.path.isfile("./" + f) else shutil.copytree(f,f + ".old") for f in os.listdir(".")]'
Observe que isso falhará se say directory_one.old/
já existir