Сократите имя файла до n символов, сохранив расширение файла - PullRequest
0 голосов
/ 14 марта 2020

Я пытаюсь сократить имя файла, сохраняя расширение.

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

Например, я пытаюсь переименовать abcdefghijklmnop.txt в abcde.txt

Я бы хотел просто отрезать конец имени файла, чтобы общая длина символа не превышала [ в этом примере] 5 символов.

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


Основой для этого в конечном счете является то, что я хочу массово усечь имена файлов, длина которых превышает 135 символов, чтобы я мог rsyn c файлы в зашифрованный общий ресурс на NAS-устройстве Synology.

Я нашел хороший способ поиска по всем именам файлов, длина которых превышает 135 символов: find . -type f | awk -F'/' 'length($NF)>135{print $0}'

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

Любая помощь будет оценена, спасибо!

Обновление для уточнения:

Я хотел бы использовать однострочник с таким синтаксисом:

find . -type f | awk -F'/' 'length($NF)>135{print $0}' | some_code_here_to_shorten_the_filename_while_preserving_the_extension

Ответы [ 3 ]

1 голос
/ 15 марта 2020

С помощью GNU find и bash:

export n=10 # change according to your needs
find . -type f                      \
     ! -name '.*'                   \
       -regextype egrep             \
     ! -regex '.*\.[^/.]{'"$n"',}'  \
       -regex '.*[^/]{'$((n+1))',}' \
       -execdir bash -c '
    echo "PWD=$PWD"
    for f in "${@#./}"; do
        ext=${f#"${f%.*}"}
        echo mv -- "$f" "${f:0:n-${#ext}}${ext}"
    done' bash {} +

Это выполнит dry -запуск, то есть покажет папки, за которыми следуют команды, которые должны быть выполнены внутри них. Как только вы довольны выводом, вы можете опустить echo перед mvecho "PWD=$PWD" строкой, если хотите), и он на самом деле переименует все файлы, имена которых превышают n символов, на имена, точно * Длина 1008 * символов, включая расширение.

Обратите внимание, что это исключает скрытые файлы и файлы, чьи расширения равны или длиннее n (например, .hidden, app.properties где n=10).

0 голосов
/ 15 марта 2020

использовать bash манипуляции со строками
Подробности: https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/string-manipulation.html.
прокрутить до «Извлечение подстроки»

Пример ниже сократить имя файла до 10 символов, сохраняя расширение

~ % cat test   

rawFileName=$(basename "$1")
filename="${rawFileName%.*}"
ext="${rawFileName##*.}"

if [[ ${#filename} < 9 ]]; then
    echo ${filename:0:10}.${ext}
else
    echo $1
fi

И тесты:

~ % ./test 12345678901234567890.txt
1234567890.txt
~ % ./test 1234567.txt             
1234567.txt
0 голосов
/ 15 марта 2020

Обновление

Поскольку ваш файл распространяется в виде дерева каталогов, вы можете использовать мой оригинальный подход, но передавая сценарий команде sh, передаваемой параметру -exec find:

n=5 find . -type f -exec sh -c 'f={}; d=${f%/*}; b=${f##*/}; e=${b##*.}; b=${b%.*}; mv -- "$f" "$d/${b:0:n}.$e"' \;

Исходный ответ

Если имя файла находится в переменной x, тогда ${x:0:5}.${x##*.} должен выполнить эту работу.

Так что вы можете сделать что-то вроде

n=5 # or 135, or whatever you like
for f in *; do
  mv -- "$f" "${f:0:n}.${f##*.}"
done

Очевидно, что это предполагает отсутствие столкновений между сокращенными именами. Если есть столкновения, то выживет только один ! Так что будь осторожен.

...