Intereting Posts
Как сделать tr знанием символов non-ascii (unicode)? Мой сервер постоянно атакуется Debian install unsuccessfull: установки DVD, dd, cat, Unetbootin, YUMI, Rufus, Live CD не работают Раскройте и разблокируйте файл .tar.gz, используя cat, tar и gzip в одной командной строке убивать или удалять всех клиентов из работающего vncserver без перезапуска сервера Команда запуска, когда температура превышает пороговое значение, без демона Что такое снимок SVN? apt-get продолжает терпеть неудачу Как mount определяет параметры установки по умолчанию для вновь подключенных файловых систем? Легкая изолированная среда linux Как ограничить ресурсы, которые приложение может использовать на веб-сервере linux 32-разрядный 64-разрядный процессорный режим на Linux Как добиться быстрого переключения пользователей с помощью нескольких графических адаптеров, предотвратить использование виртуального терминала? Проверьте, подключен ли сетевой кабель, не подключая интерфейс Контроллер Logitech не переходит в виртуальную машину Centos как джойстик

найти проблему в скрипте bash

Я пишу программу, печатающую файл и каталог каталога. Но я должен игнорировать определенный файл. Мы храним их в .ignorefile .

Итак, чтобы получить только тот файл, который я хочу, я использую функцию find. Но каждый раз я получаю такую ​​же ошибку: No such file or directory .

И, когда я пытаюсь использовать терминал, он отлично работает с теми же аргументами.

Пример :

  • В моем файле игнорирования у меня есть: *.txt, *.cpp

  • Когда я выполняю мой .sh файл, я помещаю два аргумента: файл игнорирования и каталог.

  • Затем, когда я просматриваю весь текст в своем файле для создания файлов аргументов, я вызываю функцию store() .

Здесь вы можете увидеть мой код:

  function store(){ dir="$1" find_arg="$2" # Dir ! -name '*.txt' ! -name '*.cpp' -print echo $find_arg cmd=`find "$find_arg"` echo $cmd } 

Здесь функция, которая создает find_args:

 function backup() { if [ $1="-i" ] && [ -f $2 ] then backignore=$2 if [ $3="-d" ] && [ -d $4 ] then directory=$4 find_arg=" $directory" while IFS='' read -r line || [[ -n "$line" ]]; do find_arg+=" ! -name " find_arg+="'" find_arg+=$line find_arg+="'" done < "$backignore" find_arg+=" -print" store $directory "$find_arg" else echo "please entrer a right directory" fi else echo "Please enter a right ignore file" fi } backup $1 $2 $3 $4 

Я называю файл «sh»

 ./file.sh -i ignorefile -d Source 

вывод:

 Source ! -name '\*.cpp' ! -name '\*.txt' -print Source/unix_backup/example_files/backignore Source/unix_backup/example_files/Documents/rep1/file3.txt Source/unix_backup/example_files/Documents/rep1/file4.cpp Source/unix_backup/example_files/Documents/rep3 Source/unix_backup/example_files/Documents/rep3/rep4 Source/unix_backup/example_files/Documents/rep3/rep4/file7.txt Source/unix_backup/example_files/Documents/rep3/rep4/file8.cpp 

find_arg передается как один аргумент (из-за двойных кавычек), что означает, что find пытается найти все файлы в каталоге Dir ! -name '*.txt' ! -name '*.cpp' -print Dir ! -name '*.txt' ! -name '*.cpp' -print Dir ! -name '*.txt' ! -name '*.cpp' -print (Да, это допустимое имя каталога). Попробуйте printf '%q\n' "$find_arg" чтобы увидеть фактические аргументы, переданные для find . Кроме того, если ваша оболочка поддерживает массивы, вы, вероятно, должны использовать их для хранения аргументов . И используйте больше котировок ™ ! И не используйте здесь evalfind будет печатать имена файлов просто отлично.

  1. Вы говорите, что ваш .ignorefile имеет *.txt, *.cpp но из показанного результата он выглядит как \*.txt, \*.cpp . Экранирование * является источником вашей проблемы, оно говорит find чтобы исключить файлы с буквальной звездочкой, а не использовать ее в качестве шаблона glob. Поэтому не делайте этого.

  2. Эта версия вашего скрипта исправляет несколько недостатков и немного упрощает его. Помимо всего прочего, он отделяет обработку arg (и использует getopts, которая встроена в sh) из основной логики функции backup() .

 function store() { echo find "$@" find "$@" } function backup() { directory="$1" backignore="$2" # skip comments and blank lines sed -e 's/#.*// ; /^[[:space:]]*$/d' "$backignore" | while IFS= read -r line ; do find_arg+=" ! -name '$line'" done find_arg+=" -print" store "$directory" $find_arg } usage() { echo "$(basename $0) [ -d directory ] [ -i ignorefile ]" exit 1 } directory='' backignore='.ignorefile' # default while getopts "i:d:h" opt ; do case "$opt" in d) directory="$OPTARG" ;; i) backignore="$OPTARG" ;; *) usage ;; esac done [ -z "$directory" ] && echo "Please provide a directory." && usage backup "$directory" "$backignore"