Linux: удалить расширения для нескольких файлов

У меня много файлов с расширением .txt. Как удалить расширение .txt для нескольких файлов в Linux?

я нашел это

rename .old .new *.old

заменяет расширение .old на расширение .new

Также я хочу сделать это для файлов в подпапках.


person rp101    schedule 22.12.2010    source источник
comment
Я думаю, заголовок должен быть таким: Linux: переименовать расширения файлов для нескольких файлов.   -  person Roberth Solís    schedule 02.07.2020
comment
Да, это определенно привело меня сюда по ошибке, этот вопрос касается изменения расширения, а не его удаления.   -  person Tofandel    schedule 25.03.2021


Ответы (9)


rename немного опасен, поскольку согласно его странице руководства:

rename переименует указанные файлы, заменив первое вхождение...

Он с радостью сделает что-то не так с такими именами файлов, как c.txt.parser.y.

Вот решение с использованием find и bash:

find -type f -name '*.txt' | while read f; do mv "$f" "${f%.txt}"; done

Имейте в виду, что это сломается, если имя файла содержит новую строку (редко, но не невозможно).

Если у вас есть GNU find, это более надежное решение:

find -type f -name '*.txt' -print0 | while read -d $'\0' f; do mv "$f" "${f%.txt}"; done
person thkala    schedule 22.12.2010
comment
Это верно в отношении util-linux-ng версии rename, но версия сценария Perl может выполнять rename 's/.txt$//' *.txt - person Dennis Williamson; 22.12.2010
comment
вам не хватает тока. что касается места, в которое вы хотите запустить. может быть, это мой вариант поиска OSX, или мой путь установлен неправильно - person bgs; 09.08.2013
comment
@bgs: большинство (все?) дистрибутивов Linux используют поиск GNU, который по умолчанию имеет значение . когда аргумент не указан - person thkala; 10.08.2013
comment
да, не забудьте указать спецификатор каталога, если вы работаете на Mac. например find . -type f -name '*.txt' | while read f; do mv "$f" "${f%.txt}"; done - person lolski; 25.10.2013
comment
Почему второй более прочный, чем первый? - person Qian Chen; 05.10.2018

Я использую это:

find ./ -name "*.old" -exec sh -c 'mv $0 `basename "$0" .old`.new' '{}' \;
person Chris Cowan    schedule 05.06.2013
comment
спасибо, я не знал этого синтаксиса, и он также работает на MacOSX (в котором отсутствует собственный rename ). - person Utopik; 15.07.2013
comment
Вы должны были добавить имя каталога на случай, если цель находится во вложенной папке: find ./ -name *.old -exec sh -c 'mv $0 dirname "$0"/basename "$0" .old.new' '{}' \; - person Séverin; 29.05.2017

Perl-версия rename может удалить расширение следующим образом:

rename 's/\.txt$//' *.txt

Это можно комбинировать с find, чтобы также создавать подпапки.

person Andrew S    schedule 06.11.2013

Вы можете явно передать пустую строку в качестве аргумента.

rename .old '' *.old

А с подпапками find . -type d -exec rename .old '' {}/*.old \;. {} заменяет запись, найденную с помощью find, а \; завершает список аргументов для команды, указанной после -exec.

person robert    schedule 22.12.2010
comment
Я не знаю, какую версию rename вы там использовали, но здесь она не работает в версии для Debian, которая представляет собой сценарий perl, использующий регулярное выражение для аргументов. Это работает: $ rename 's/\.old//' *.old - person paradroid; 22.06.2021

Если это поможет, вот как я это делаю с zsh:

for f in ./**/*.old; do
    mv "${f}" "${f%.old}"
done

Конструкция ${x%pattern} в zsh удаляет кратчайшее вхождение pattern в конце $x. Здесь он абстрагируется как функция:

function chgext () {
    local srcext=".old"
    local dstext=""
    local dir="."

    [[ "$#" -ge 1 ]] && srcext="$1"
    [[ "$#" -gt 2 ]] && dstext="$2" dir="$3" || dir="${2:-.}"

    local bname=''
    for f in "${dir}"/**/*"${srcext}"; do
        bname="${f%${srcext}}"
        echo "${bname}{${srcext} → ${dstext}}"
        mv "${f}" "${bname}${dstext}"
    done
}

Использование:

chgext
chgext src
chgext src dir
chgext src dst dir

Where `src` is the extension to find (default: ".old")
      `dst` is the extension to replace with (default: "")
      `dir` is the directory to act on (default: ".")
person svvac    schedule 05.06.2017

В Fish вы можете сделать

for file in *.old
      touch (basename "$file" .old).new
end
person Bruno Alano    schedule 02.08.2016

Для подпапок:

for i in `find myfolder -type d`; do
  rename .old .new $i/*.old
done
person Konrad Garus    schedule 22.12.2010
comment
Это может вызвать проблемы, если в имени папки есть пробел. - person robert; 22.12.2010

выполнить в bash linux

for i in *;do mv ${i} ${i/%.pdf/} ;done
person shahin aref    schedule 03.03.2019

командная строка

find -type f -name '*.js' | xargs rm
person Yefrid rios mora    schedule 22.06.2020
comment
Это не переименовывает расширение файла, это удаляет файлы! - person Eric; 23.06.2020
comment
Это не переименовывает расширение файла .txt, оно удаляет файлы с расширением .js. - person karel; 23.06.2020
comment
Передача результатов find через xargs для индивидуального переименования каждого файла имеет смысл и позволяет избежать цикла while. Но, как упоминали другие комментаторы, это просто удаляет найденные файлы, а не переименовывает их! - person dbc; 23.06.2020
comment
Я думаю, что этот ответ, если в соответствии с заголовком, я искал удалить, а не переименовать, и это работает, я думаю, что автору нужно переименовать заголовок, это нормально, rp101? - person Roberth Solís; 02.07.2020