Удалить путь из выходных данных команды find

29

У меня есть сценарий bash для развертывания кода из бета-среды в производственной среде, но в настоящее время я вынужден вручную добавить список файлов в текстовый файл, а иногда мне не хватает некоторых. В основном мой сценарий развертывания cat / loops копирует файлы. (экспорт / импорт дБ, но это не актуально .. лол)

В любом случае, я хотел бы использовать findкоманду для создания списка файлов, измененных за последние 14 дней. Проблема в том, что мне нужно удалить путь, ./чтобы скрипт развертывания работал.

Вот пример использования команды find:

находить . -type f -mtime -14> deploy.txt

Вот строчка, которую коты deploy.txtв моем сценарии развертывания:

for i in `cat deploy.txt`; do cp -i /home/user/beta/public_html/$i /home/user/public_html/$i; done

Любая идея, как сделать это с помощью сценариев Bash?

Благодарность!

Mikey1980
источник
3
Есть ли причина, по которой вы не можете просто использовать rsync для этого? Звучит так, как будто вы пытаетесь изобрести колесо и сделать его треугольником.
ThatGraemeGuy
однако перед развертыванием действительная точка проверяется, и файл deploy.txt проверяется, и все, что требует исправления, удаляется
Mikey1980
1
Может быть, запустить rsync в --dry-runрежиме и вывести его в файл для просмотра?
Zoredache

Ответы:

36

Вы можете использовать параметр -printfкомандной строки %fдля печати только имени файла без какой-либо информации каталога

find . -type f -mtime -14 -printf '%f\n' > deploy.txt

или вы можете использовать sed, чтобы просто удалить ./

find . -type f -mtime -14 | sed 's|^./||' >deploy.txt
Iain
источник
Я верю, что ты должен сбежать /..
EEAA
5
Не тогда, когда вы используете |в качестве разделителя.
user9517 поддерживает GoFundMonica
3
Использование %fудалит все каталоги, а не только ./. Это нарушит его сценарий развертывания, если какой-либо из файлов, возвращаемых им find, находится в подкаталогах.
Джеймс Снерингер
2
@Iain Тебе нужно сбежать от этого .. И, возможно, лучше всего использовать якорь начала строки:s|^\./||
Джеймс О'Горман
12
Используйте %Pвместо %f. Это просто отрезало путь, указанный в командной строке.
Правда
12

./Должно быть безвредным. Большинство программ будут относиться /foo/barи /foo/./barкак к эквиваленту. Я понимаю, что это выглядит не очень хорошо, но на основании того, что вы опубликовали, я не вижу причин, по которым это может привести к сбою вашего сценария.

Если вы действительно хотите избавиться от него, sedвозможно, это самый чистый способ:

find . -type d -mtime 14 | sed -e 's,^\./,,' > deploy.txt

Если вы работаете в системе с GNU find (например, в большинстве систем Linux), вы можете сделать это за один раз find -printf:

find . -type d -mtime 14 -printf "%P\n" > deploy.txt

В %Pвозвращает полный путь каждого найденного файла, минус путь , указанный в командной строке, вплоть до и включая первый слэш. Это сохранит все подкаталоги в вашей структуре каталогов.

Джеймс Снерингер
источник
1
./Приставка на самом деле функция; без него передача данных в другие команды не будет работать правильно, например, для имен файлов, начинающихся с тире.
tripleee
1
@tripleee - я понимаю полезность этого, но OP специально спросил, как его убрать, потому что это вызывало проблемы для его сценария развертывания. Конечно, могут быть лучшие способы сделать то, что ему нужно, но это кроличья нора, выходящая далеко за рамки того, о чем спрашивали.
Джеймс
7

Зачем тебе раздеваться ./? Это действительно иметь в пути. Так

cp -i dir1/./somefile dir2/./somefile

это просто хорошо!

Но если вы хотите удалить имя каталога в find, вы можете использовать %Parg для -printf.

человек найти (1) говорит:

         %P     File's name with the name of the  command  line  argument
                 under which it was found removed.

Пример

$ find other -maxdepth 1
other
other/CVS
other/bin
other/lib
other/doc
other/gdbinit
$ find other -maxdepth 1 -printf "%P\n"

CVS
bin
lib
doc
gdbinit

Следите за первой пустой строкой! Если Вы хотите избежать этого, используйте-mindepth 1

$ find other -mindepth 1 -maxdepth 1 -printf "%P\n"
CVS
bin
lib
doc
gdbinit
TrueY
источник
3

Ну, у вас есть несколько вариантов. Вы можете использовать -printfопцию в find, чтобы распечатать только имя файла, или вы можете использовать инструмент вроде sed, чтобы просто вырезать ./.

# simply print out the filename, will break if you have sub-directories.
find . -mtime -14 -printf '%f\n'

# strip a leading ./
find .  -mtime -14 | sed -e 's/^\.\///'
Zoredache
источник
Можете ли вы дать мне пример его использования? Извините, Linux на самом деле не моя удача
Mikey1980
2
Посмотрите еще раз, есть примеры.
Zoredache
Согласитесь - просто попробуйте, вам не повредит что-либо, использующее комбинацию find и sed.
EEAA
3

Решение "find -printf" не будет работать во FreeBSD, потому что у find нет такой опции. В этом случае AWK может помочь. Возвращает фамилию ($ NF), поэтому может работать на любой глубине.

find /usr/local/etc/rc.d -type f | awk -F/ '{print $NF}'

PS: взято из книги Д.Тэнсли "Программирование под Linux и Unix shell"

user221341
источник
2

Быстрое решение, если я правильно понимаю вопрос, заключается в использовании cutна выходе findкоманды:

$> find . -type f -mtime -14 | cut -b 3- > deploy.txt

Это удалит первый символ из каждой строки результата (в вашем случае ./). Вероятно, не лучшее решение, но работает в вашем сценарии.

Алессандро Дотти Контра
источник
1

sed идеально подходит для такого рода вещей.

$ find . -type f -mtime -14 find . | sed 's/^\.\///' > deploy.txt
EEAA
источник
1

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

Я бы предложил использовать расширение параметров оболочки для удаления символов из каждого имени файла:

find . -mtime -14 -exec sh -c 'printf "${0#./}\n"' {} \; >deploy.txt

Если вам действительно нравятся каналы, вы можете использовать «безопасный» разделитель, например ноль, с xargs для получения каждого имени файла:

find . -mtime -14 -print0 | xargs -0 -n 1 sh -c 'printf "${0#./}\n"' >deploy.txt

Помните, что вывод этого НЕ НЕ разделен нулем, поэтому, хотя этого может быть достаточно для проверки глазного яблока, ни одно из этих решений не создает файл deploy.txt, который можно безопасно использовать для автоматизации, если вы не очень уверены в своем источнике имена файлов.

Ghoti
источник