Команда поиска работает из командной строки, но не в скрипте

#regex #linux #bash #find

#регулярное выражение #linux #bash #Найти

Вопрос:

Я работаю над процессом, который должен выполняться каждую ночь и будет tar.gz большой список файлов (слишком большой, чтобы использовать команду tar). Чтобы обойти это, я могу создать список файлов, которые я хочу, чтобы tar архивировал, и передать его. Обычно я делаю это вручную, но я бы хотел автоматизировать это с помощью crontab.

В данном случае используется ОС RedHat Enterprise 6.3 (Сантьяго).

У меня есть следующий сценарий оболочки bash:

 #!/bin/bash

now=$(date  "%Y%m%d")

TARGET_DIR=/usr/share/data

FILE_LIST=/home/user/txt-files/data-as-of-$now.txt

if [ -e $FILE_LIST ];
then
    rm -rf $FILE_LIST
fi

CMD="find $TARGET_DIR -regextype posix-extended -regex ".*/$now.*" -fprint $FILE_LIST"

echo $CMD

findCmd=`$CMD`

if [ $? -ne 0 ];
then
    echo "command failed; $findCmd"
fi
 

Скрипт работает нормально, но ничего не записывает в файл, указанный в аргументе -fprint . Если я беру команду, которая выводится эхом, и копирую и вставляю ее в cli, она работает так, как я ожидаю, и в моем файле есть список файлов, которые я хочу.

 find /usr/share/data -regextype posix-extended -regex ".*/20140624.*" -fprint /home/user/txt-files/data-as-of-20140624.txt
 

Я предполагаю, что в регулярном выражении есть что-то странное, что неправильно интерпретируется при запуске как скрипт, но не как команда из командной строки. Я читал в других темах о необходимости заключать звездочку в кавычки, и я пробовал одинарный тик и двойной тик, ни один из них, похоже, не работает. Я также пробовал обратный способ выполнения команды и способ $(), оба дают одинаковый результат.

Если бы я получал какие-либо ошибки или сообщения, это было бы менее сложным. Если кто-нибудь может посмотреть и посмотреть, делаю ли я что-то явно неправильное, я был бы признателен за указатель!

Если я выполняю команду с помощью bash -x, я получаю этот вывод:

 [user@data-provider bin]$ bash -x tgz2.sh
   date  %Y%m%d
  now=20140624
  TARGET_DIR=/usr/share/data
  FILE_LIST=/home/user/txt-files/data-as-of-20140624.txt
  '[' -e /home/user/txt-files/data-as-of-20140624.txt ']'
  rm -rf /home/user/txt-files/data-as-of-20140624.txt
  CMD='find /usr/share/data -regextype posix-extended -regex '''.*/20140624.*''' -fprint /home/user/txt-files/data-as-of-20140624.txt'
  echo find /usr/share/data -regextype posix-extended -regex ''''.*/20140624.*'''' -fprint /home/user/txt-files/data-as-of-20140624.txt
find /usr/share/data -regextype posix-extended -regex '.*/20140624.*' -fprint /home/user/txt-files/data-as-of-20140624.txt
   find /usr/share/data -regextype posix-extended -regex ''''.*/20140624.*'''' -fprint /home/user/txt-files/data-as-of-20140624.txt
  findCmd=
  '[' 0 -ne 0 ']'
 

Комментарии:

1. Я пробовал это как со мной, так и с sudo. Из командной строки, как я, это работает нормально. Когда я запускаю скрипт от своего имени, я ничего не получаю; тот же результат с sudo — нет вывода.

2. Попробуйте это: findCmd=$(eval "$CMD")

3. Спасибо! Я попробовал это; теперь я получаю «нет такого файла или каталога». Когда я выполняю ‘ls’ от своего имени в каталоге, который я ищу, и в каталоге, в который я хочу записать, они оба существуют, и я могу их перечислить. Я проверил права собственности и разрешения на каталоги, и я владею ими и могу писать в них.

4. Это почти наверняка проблема, -fprint поскольку она должна создавать файл независимо от того, найдено что-либо или нет.

5. @BroSlow — Возможно, но он создает файл, но он пустой. Когда я запускаю ее из командной строки, она работает нормально. Я выполнил множество сценариев с использованием find, но с -name или -type, и это сработало. Мне кажется, что это больше связано с регулярным выражением, но опять же, если бы я знал, что я делаю, у нас не было бы этого чата. 😉

Ответ №1:

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

 find $TARGET_DIR -regextype posix-extended -regex ".*/$now.*" -fprint $FILE_LIST
 

Проблема с исходным синтаксисом, который я тестировал с

 cmd="find -regex '.*/test.*' -fprint out.txt
$cmd
 

заключается в том, что он запускается как

 find -regex ''''.*/test.*'''' -fprint out.txt
 

но не совсем уверен, почему подстановка переменных добавляет ошибочные одинарные кавычки.