erro cp no script

erro cp no script

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 lscomando, 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 ifinstruçã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 findcomando de uma linha, sem a necessidade de analisar lsou 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 é findoperar em todos os arquivos do .diretório (atual) e chamar cppor cada arquivo (portanto \;). Por findser recursivo, temos que limitar a profundidade da pesquisa, portanto, -maxdepthsinalizar e -mindepthsinalizar é 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: cpainda reclamará dos diretórios. Existem algumas maneiras de lidar com isso.

1) você pode filtrar apenas arquivos se esse for seu objetivo com -type fsinalizador findcomo

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 findo 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

informação relacionada