ошибка cp в скрипте

ошибка cp в скрипте

При запуске следующего скрипта возникает следующая ошибка:

cp: cannot stat ls

Содержание сценария

#!/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

Кто-нибудь видит проблему?

решение1

Одна из главных ошибок заключается в том, что вы пытаетесь использовать команду ls, но переменная LIST содержит только строку 'ls'. Вы можете использовать подстановку команд с синтаксисом $(command). Я бы не советовал этого делать в этом случае, так как это не даст вам информацию в формате, который вы можете легко использовать. Это почти всегдаошибка при анализе выводаls.

В этом случае вам следует использовать сопоставление с образцом оболочки, также известное какподстановка.

Вместо этого я бы предложил следующий метод в вашем сценарии:

#!/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
  • При этом используется подстановка символов оболочки для сопоставления всех файлов в каталоге. ./* означает все в текущем каталоге ( .).
  • Оператор ifпроверяет, является ли совпадение файлом (для каталогов и ссылок проверка невозможна), и, если это так, выполняет последовательность копирования.
  • Я изменил имена переменных на строчные, поскольку системные переменные среды пишутся заглавными буквами, чтобы избежать нежелательных конфликтов имен.

решение2

Ну, в вашем скрипте есть небольшая ошибка. В четвертой строке вы имели в виду выполнитьлспоэтому его не следует заключать в одинарные кавычки, а следует обернуть внутри символа``. Итак, ваш скрипт меняется следующим образом

LIST=`ls`

Попробуйте обновить скрипт, как указано выше.

Однако желательно не использовать его $(ls)вообще, а отдать предпочтение подстановке оболочки в заголовке цикла.

for i in *; do

ПодобноГ-н Дэвид Андерссонпрокомментировал ниже, что это можно использовать с кавычками для значений переменных ("$i") для следующих за ним операторов, иначе могут возникнуть проблемы с пробелами в именах файлов. Вы можете предотвратить это, используя find в сочетании с заменой процесса:

while read l; do
    i=$(basename "$l")
done < <(find . -name '*' -maxdepth 1)

Подробный ответ со сценарием и пояснениями дан ниже.Г-н Арроникал. Пожалуйста, ссылайтесь на него для улучшения сценариев в будущем.

решение3

Версия команды «find»

Ваш скрипт может быть реализован как однострочная findкоманда, без необходимости разбора lsили возни с подстановками и т. д.

Ваша цель, насколько гласит вопрос, сделать копии всех файлов в текущем каталоге. Для этого соответствующая команда будет:

find . -maxdepth 1 -mindepth 1 -exec cp {} {}".old" \;

Что это делает, так это то, что findработает со всеми файлами в .(текущем) каталоге и вызывает cpдля каждого файла (следовательно \;). Поскольку findэто рекурсивно, это мы должны ограничить глубину поиска, следовательно, -maxdepthфлаг, а -mindepthфлаг — это избежать перечисления .в качестве одного из результатов поиска.

Пример запуска:

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

ПРИМЕЧАНИЕ: cpвсе равно будет жаловаться на каталоги. Есть несколько способов справиться с этим.

1) вы можете отфильтровать только файлы, если это ваша цель, с помощью -type fфлага в findlike

find . -mindepth 1 -maxdepth 1 -type f -exec cp {} {}".old" \;

2) Используйте cp -r также для создания копий каталогов

find . -mindepth 1 -maxdepth 1 -exec cp -r {} {}".old" \;

Однострочник на Python

Этот вариант немного длиннее findпредыдущего, но все равно выполняет свою работу и не имеет проблем со специальными именами файлов.

python -c 'import shutil; import os;[shutil.copyfile(f,f + ".old") for f in os.listdir(".") if os.path.isfile("./" + f)]'

Пример запуска:

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

Чтобы включить каталоги, используйтеshutil.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(".")]'

Обратите внимание, что это не удастся, если, скажем, directory_one.old/уже существует

Связанный контент