#linux #bash #find
#linux #bash #Найти
Вопрос:
У меня есть папка с многочисленными версиями файлов (их тысячи), каждая с уникальной отметкой даты / времени в качестве расширения файла. Например:
./one.20190422
./one.20190421
./one.20190420
./folder/two.txt.20190420
./folder/two.txt.20190421
./folder/folder/three.mkv.20190301
./folder/folder/three.mkv.20190201
./folder/folder/three.mkv.20190101
./folder/four.doc.20190401
./folder/four.doc.20190329
./folder/four.doc.20190301
Мне нужно получить уникальный список базовых файлов. Например, для приведенного выше примера это был бы ожидаемый результат:
./one
./folder/two.txt
./folder/folder/three.mkv
./folder/four.doc
Я придумал приведенный ниже код, но мне интересно, есть ли лучший, более эффективный способ.
# find all directories
find ./ -type d | while read folder ; do
# go into that directory
# then find all the files in that directory, excluding sub-directories
# remove the extension (date/time stamp)
# sort and remove duplicates
# then loop through each base file
cd "$folder" amp;amp; find . -maxdepth 1 -type f -exec bash -c 'printf "%sn" "${@%.*}"' _ {} | sort -u | while read file ; do
# and find all the versions of that file
ls "$file".* | customFunctionToProcessFiles
done
done
Если это имеет значение, конечная цель — найти все версии определенного файла в группах базового файла и обработать их для чего-то. Итак, мой план состоял в том, чтобы получить базовые файлы, затем просмотреть список и найти все файлы версий. Итак, снова используя приведенный выше пример, я бы сначала обработал все one.*
файлы, затем two.*
файлы и т.д…
Есть ли лучший, быстрый и / или более эффективный способ добиться этого?
Некоторые примечания:
- Потенциально могут быть тысячи файлов. Я знаю, что мог бы просто выполнить поиск по всем файлам из корневой папки, удалить расширение даты / времени, отсортировать и получить уникальный, но поскольку файлов могут быть тысячи, я подумал, что было бы эффективнее перебирать каталоги.
- Расширение файла с отметкой даты / времени не находится под моим контролем, и это не всегда могут быть просто цифры. Единственное, что я могу гарантировать, это то, что он заканчивается через определенный период. И независимо от формата, в котором указана дата / время, все файлы будут использовать его совместно — не будет файлов с одним форматом и других файлов с другим форматом.
Комментарии:
1. ну, у вас есть хотя бы примеры другого возможного формата? Имеют ли они общий шаблон?
2. Отметка даты / времени — это параметр конфигурации, который пользователь может установить, используя форматы, принятые
date
. Таким образом, я не могу разработать шаблон. Единственное, что я могу гарантировать, это то, что он будет в конце, после периода, и все файлы будут иметь одинаковый формат.3. Гм.
date
позволяет выводить буквально все .4. ДА. Но скрипт не позволит пользователю указывать период в своем пользовательском формате даты / времени.
Ответ №1:
Вы можете использовать find ./ -type f -regex
для прямого поиска файлов
find ./ -type f -regex '.*.[0-9] '
./some_dir/asd.mvk.20190422
./two.txt.20190420
Кроме того, передайте результат вашей функции через xargs
без необходимости while
циклов
re='(.*)(.[0-9]{8,8})'
find ./ -type f -regextype posix-egrep -regex "$re" |
sed -re "s/$re/1/" |
xargs -r0 customFunctionToProcessFiles
Комментарии:
1. Я обновил вопрос с более подробной информацией. Я забыл упомянуть, что отметка даты / времени не всегда может быть просто цифрами.
2. Для меня не очевидно, как ваш xargs группирует вызовы по имени базового файла. Похоже, что пользовательская функция вызывается для каждого файла по отдельности.