Я работаю над сценарием оболочки, и теперь я пришел к тому, что мне нужно переименовать файлы, начинающиеся с цифры и пробел , удалив этот шаблон и переместив его в определенную папку, которая в основном строка между вторым и третьим "-"

example :
001 - folder1 - example.doc > /folder1/example.doc 
002 - folder2 - someexample.doc > /folder2/someexample.doc 
003 - folder3 - someotherexample.doc > /folder3/someotherexample.doc

Я хочу сделать что-то вроде

find /tmp -name '*.doc' -print | rename .... ... 

Что я не знаю, это:
Как узнать, что файл начинается с числа,
и второй
- как взорвать имя с помощью шаблона типа "-" и сказать переименовать, чтобы поместить файл в папку

0
Max Muster 1 Сен 2017 в 15:26

4 ответа

Лучший ответ

Ответ очень близок к предложению Рамана, я удалил printf, добавил часть, которая создает папку, и добавил часть, удалив начальную и конечную пробел.

В итоге это выглядит так:

find . -regex '^.*[0-9].*\.doc$' | awk -F- '{ print "mkdir \""gensub(" $","","g",gensub("^ ","","g",$2))"\" \nmv \""$f"\" \"./"gensub(" $","","g",gensub("^ ","","g",$2))"/"gensub(" $","","g",gensub("^ ","","g",$2"-"$3))"\"" }'|sh

Спасибо всем за предложения.

0
Max Muster 1 Сен 2017 в 22:43

С пристальным взглядом:

find . -regex '^.*[0-9]+ - [a-zA-Z]+[0-9] - [a-zA-Z]+\.doc$' -printf %f | awk -F- '{ print "mv \""$0"\" /"gensub(" ","","g",$2)"/"gensub(" ","","g",$3) }'

Используйте find с регулярными выражениями, а затем проанализируйте вывод до awk, чтобы выполнить команду перемещения.

Когда вы проверите, что команды в порядке, запустите команды с.

find . -regex '^.*[0-9]+ - [a-zA-Z]+[0-9] - [a-zA-Z]+\.doc$' -printf %f | awk -F- '{ print "mv \""$0"\" /"gensub(" ","","g",$2)"/"gensub(" ","","g",$3) }' | sh

Будьте осторожны, что такая стратегия может быть подвержена риску введения команд.

1
Raman Sailopal 1 Сен 2017 в 12:56

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

while read f; do
    if [[ "$f" =~ ^\./[0-9]+\ -\ ([^\ ]+)\ -\ (.+\.doc)$ ]]; then
        mkdir -p "${BASH_REMATCH[1]}"
        mv "$f" "${BASH_REMATCH[1]}/${BASH_REMATCH[2]}"
    fi
done < <(find . -maxdepth 1 -name '[0-9]*.doc')

< Сильный > Разъяснения :

  • find . -maxdepth 1... ограничивает поиск текущим каталогом.
  • find...-name '[0-9]*.doc соответствует только файлам, имена которых начинаются как минимум с одной цифры и заканчиваются .doc.
  • Регулярное выражение моделирует ваши исходные имена файлов (с начальными ./, которые find добавляет). Он содержит два подвыражения, заключенных в (...), соответствующих имени папки и имени файла назначения. Эти подвыражения сохраняются bash в массиве BASH_REMATCH, если есть совпадение, в позициях 1 и 2 соответственно.
  • Регулярное выражение удаляет начальные и конечные пробелы из имени папки назначения и начальные пробелы из имени файла назначения (я предполагаю, что это то, что вы хотите).
1
Renaud Pacalet 1 Сен 2017 в 13:21

Если возможно, я бы избегал find и просто использовал бы совпадение регулярных выражений bash. Если вам не нужен рекурсивный поиск /tmp (как это делает ваша версия find), это должно работать в любой версии bash:

regex='^[[:digit:]]+ - (.+) - (.+)$'
for f in /tmp/*.doc; do
    [[ $f =~ /tmp/$regex ]] || continue
    mv -- "$f" "/${BASH_REMATCH[1]/${BASH_REMATCH[2]}"
done

Если вам нужно выполнять рекурсивный поиск, и вы используете bash 4 или более позднюю версию, вы можете использовать параметр globstar:

shopt -s globstar
regex='^[[:digit:]]+ - (.+) - (.+)$'
for f in /tmp/**/*.doc; do
    b=$(basename "$f")
    [[ $b =~ $regex ]] || continue
    mv -- "$f" "/${BASH_REMATCH[1]/${BASH_REMATCH[2]}"
done
4
chepner 1 Сен 2017 в 13:25