Bash переименовать расширение рекурсивно

Я знаю, что вокруг много таких вещей, но либо они не работают рекурсивно, либо они огромны.

вот что я получил:

find . -name "*.so" -exec mv {} `echo {} | sed s/.so/.dylib/` ;

когда я просто запускаю часть поиска, она дает мне список файлов. Когда я запускаю часть sed, она заменяет любую .так и с .dylib нужна. Когда я управляю ими вместе, они не работают.

Я заменил mv на echo, чтобы посмотреть, что произошло:

./AI/Interfaces/C/0.1/libAIInterface.so ./AI/Interfaces/C/0.1/libAIInterface.so

ничего не заменяется вообще!
Что случилось?

6 ответов


это все правильно:

find -L . -type f -name "*.so" -print0 | while IFS= read -r -d '' FNAME; do
    mv -- "$FNAME" "${FNAME%.so}.dylib"
done

правильно, мы имеем в виду:

1) он переименует только расширение файла (из-за использования ${FNAME%.so}.dylib). Все остальные решения с использованием ${X/.so/.dylib} неверны, поскольку они ошибочно переименовывают первое вхождение of .so В имя файла (например,x.so.so переименован в x.dylib.so, или, еще хуже, ./libraries/libTemp.so-1.9.3/libTemp.so переименован в ./libraries/libTemp.dylib-1.9.3/libTemp.so - сообщение об ошибке).

2) он будет обрабатывать пробелы и любые другие специальные символы в именах файлов (кроме двойных кавычек).

3) он не будет изменять каталоги или другие специальные файлы.

4) он будет следовать символическим ссылкам в подкаталоги и ссылкам на целевые файлы и переименовывать целевой файл, а не саму ссылку (поведение по умолчанию find должно обрабатывать символическую ссылку, а не файл, на который указывает ссылка).


скрипт bash для переименования расширений файлов вообще

  #/bin/bash
  find -L . -type f -name '*.' -print0 | while IFS= read -r -d '' file; do
      echo "renaming $file to $(basename ${file%.}.)";
      mv -- "$file" "${file%.}.";
  done

кредиты aps2012.

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

  1. создайте файл, например под названием ext-rename (нет расширения, поэтому вы можете запустить его как команду), например,/usr/bin (убедитесь, что /usr/bin добавляется $PATH)
  2. run ext-rename [ext1] [ext2] в любом месте в терминале, где [ext1] переименование из и [ext2] - это называется. Пример использования: ext-rename so dylib, который переименует любой файл с расширением .so С тем же именем, но с расширением .dylib.

что не так, что

echo {} | sed s/.so/.dylib/
выполняется только один раз, перед find запускается, sed дано {} на его входе, который не соответствует /.so/ и остается неизменным, поэтому ваша результирующая командная строка
find . -name "*.so" -exec mv {} {}

for X in `find . -name "*.so"` 
do
 mv $X ${X/.so/.dylib}
done

если у вас есть Bash 4

#!/bin/bash

shopt -s globstar
shopt -s nullglob
for file in /path/**/*.so
do
 echo mv "$file"  "${file/%.so}.dylib"
done

ему нужна рекурсия:

#!/bin/bash

function walk_tree {
    local directory=""
    local i

    for i in "$directory"/*; 
        do
            if [ "$i" = . -o "$i" = .. ]; then 
                continue
            elif [ -d "$i" ]; then  
            walk_tree "$i"  
            elif [ "${i##*.}" = "so" ]; then
                echo mv $i ${i%.*}.dylib    
            else
                continue
            fi
        done    
}

walk_tree "."