Поскольку строки в кавычках заключены в двойные... двойные кавычки, они вообще не заключаются в кавычки.
У вас есть:
find /log/ -mtime -31 -type f -name ""*data.txt"" -printf ""cp -p %p /Backup/%Td/\n"" | sh
Это должно быть:
find /log/ -mtime -31 -type f -name "*data.txt" -printf "cp -p %p /Backup/%Td/\n" | sh
Возможно, вам не следует этого делать. Вы должны использовать find -exec
для копирования этих файлов.
Помимо проблем с синтаксисом, уже упомянутых в комментариях, ваша основная проблема с кодом заключается в том, что вы читаете то, что вы воспринимаете как несколько имен файлов, в одну строку, а затем используете эту единственную строку как одно имя файла.
Вместо того, чтобы исправлять этот аспект сценария, давайте переосмыслим то, что вы хотите сделать.
Вы хотите, чтобы пользователь предоставил одно или несколько имен файлов, затем вы хотите, чтобы ваш скрипт подсчитывал количество строк в каждом и выводил количество строк в каждом файле вместе с общим количеством строк. Вы также хотите разрешить пользователю сохранять эту информацию в выходной файл. Если имя файла не существует, вы хотите, чтобы пользователь знал об этом.
Скрипт мог бы выглядеть так:
#!/bin/sh -
wc -l -- "$@"
Тестирование без сохранения вывода:
$./script.sh cat dog cow
5 cat
2 dog
14 cow
21 total
Вызов скрипта с несуществующим именем файла:
$./script.sh cat dog cow hamster
5 cat
2 dog
14 cow
wc: hamster: No such file or directory
21 total
Сохранение вывода в файле:
$./script.sh cat dog cow hamster >output
wc: hamster: No such file or directory
$ cat output
5 cat
2 dog
14 cow
21 total
"$@"
в сценарии будет заменен списком аргументов командной строки, каждый из которых заключен в кавычки. Это означает, что если вы вызовете свой сценарий с cat
, dog
и cow
в командной строке, "$@"
в сценарии расширится до этого списка.
Утилита wc
уже выполняет все необходимые действия, включая предоставление общего итога по всем данным файлам, поэтому все, что нам нужно сделать, это вызвать ее с опцией -l
для имен файлов, перечисленных в командную строку скрипта, чтобы заставить его считать строки.
По умолчанию вывод записывается в стандартный вывод.Это дает пользователю сценария свободу легко перенаправлять вывод туда, куда он хочет.
Также обратите внимание, что намного удобнее задавать аргументы командной строки скрипта, используя завершение табуляции или шаблоны подстановки имени файла, чем вводить каждое имя файла вручную в интерактивной подсказке. В этом случае это также значительно упрощает код скрипта.
Что вы можете сделать в качестве дополнительной проверки, так это пожаловаться пользователю, если он не предоставил какие-либо имена файлов. В противном случае утилита wc
начнет чтение со стандартного ввода, что несколько сбивает с толку.
Это можно сделать разными способами, но здесь я покажу два варианта расширенного скрипта:
#!/bin/sh -
if [ "$#" -eq 0 ]; then
echo 'expected to get filename argument(s)' >&2
exit 1
fi
wc -l -- "$@"
Здесь рассматривается значение $#
, которое представляет собой количество аргументов командной строки, полученных сценарием. Если это ноль, оператор if
перейдет к оператору echo
, который выведет диагностическое сообщение, а затем завершит сценарий.
#!/bin/sh -
wc -l -- "${@?expected to get filename argument(s)}"
Это делает то же самое, но использует совсем другую механику. Расширение ${variable?word}
приведет к тому, что диагностическое сообщение в word
будет записано на выход, если "$@"
пусто или не установлено, а также завершит выполнение скрипта.
Это может выглядеть так:
$./script.sh
./script.sh[3]: @: expected to get filename argument(s)