С GNU или FreeBSD find
и GNU или BSDtar
:
find. -type f -newermt 2018-02-28 ! -newermt 2018-03-01 -print0 |
tar -cf file.tar --null -T -
(обратите внимание, что он исключает файлы, последние -измененные точно в нано -секунду 2018 -02 -28T00 :00 :00.000000000 (и может включать файл в то время, когда на следующий день ), что в файловых системах с гранулярностью нано -секунд почти никогда не произойдет, если только файлы не были созданы с touch -t
/ touch -d
или сами были извлечены из архивов, которые не хранят временные метки с суб-секундами. точность)
В соответствии с POSIX и при условии, что имена файлов не содержат символов новой строки (стандартный формат архива tar также имеет дополнительные ограничения на имена файлов):
touch -d 2018-02-28T00:00:00.start
touch -d 2018-03-01T00:00:00.end
find. -type f -newer.start ! -newer.end ! -path./.start ! -path./.end |
pax -x ustar -w > file.tar
Если вы хотите, чтобы все обычные файлы последний раз изменялись 28 февраля, а не только 2018 года, с помощью инструментов GNU:
find. -type f -printf '%Tm-%Td-%p\0' |
sed -nz 's/^02-28-//p' |
tar -cf file.tar --null -T -
Выходные данные find -ls
не подлежат пост--автоматической надежной обработке, они предназначены только для потребления человеком.
Это отчасти потому, что grep
использует регулярные выражения (на самом деле, это то, что re
в названии означает -это сокращение от g lobal r обычный e xpression p rint ).
Подстановочный знак *
в регулярных выражениях отличается от подстановочного знака *
в подстановке оболочки.
В регулярных выражениях *
означает «ноль или более ранее определенного объекта». Однако .
— это , а также подстановочный знак, означающий «один символ».
В глобах оболочки *
означает «ноль или более символов». .
вовсе не является подстановочным знаком.
Когда вы grep
для шаблона "*.txt"
, вы ищете ноль или более чего-либо, за которым следует еще ровно один символ, за которым следует литеральная строка txt
.
Когда вы grep
для шаблона "s*.txt"m you are looking for a literal
s , followed by zero or more
s s, followed by any character, followed by the literal string
txt `.
Вот почему в регулярных выражениях часто встречается .*
, что означает «один любой символ, за которым следует ноль или более любых символов». Регулярное выражение для «буквально любой комбинации символов, кроме нулевых символов».
Когда вы ls *.txt
сообщаете оболочке: «Найди любые имена файлов, соответствующие шаблону glob *.txt
, перечисли их здесь и предоставь их в качестве аргументов команде ls
.
В регулярных выражениях *
означает «любое количество предыдущих элементов», а не «любое количество любых символов», как в шаблонах оболочки. А .
означает «любой одиночный символ». Итак, чтобы найти «что угодно, за которым следует литерал .txt
», вы должны использовать .*\.txt
. Или просто \.txt
, так как обычно регулярное выражение ищет совпадение в любом месте строки.
Регулярное выражение *.txt
либо бессмысленно, либо является ошибкой, либо ищет буквальную звездочку, в зависимости от реализации. Лучше не использовать его.
С другой стороны, s*.txt
будет искать «любое количество букв s
, затем любой отдельный символ, затем литерал txt
». Это более правильное регулярное выражение, но... все еще не соответствует sample.txt
.
Вместо этого во второй команде происходит то, что, поскольку s*.txt
не заключено в кавычки, оболочка расширяет s*.txt
до того, как grep
увидит его. Если единственным подходящим файлом является sample.txt
, то grep
ищет его в выводе ls
.
Но ls
также может принимать список файлов, поэтому вы можете использовать
ls | grep '\.txt'
чтобы получить любой .txt
файл, вероятно, было бы проще просто использовать
ls *.txt
вместо этого.
обратите внимание, что grep ищет файл содержимое , в то время как первый аргумент — это ШАБЛОН поиска, а другие аргументы интерпретируются как ФАЙЛЫ для поиска
это становится более понятным при использовании флагов grep -H -o
или поместите свой grep
в скрипт и запустите его с bash -x script
, чтобы увидеть, как глобусы оболочки расширяются перед передачей в качестве аргументов