#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
но не совсем уверен, почему подстановка переменных добавляет ошибочные одинарные кавычки.