2010-01-31 2 views
12

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

Это то, что я получил:

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

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

я заменил мв с эхом, чтобы посмотреть, что случилось:

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

Ничто не заменяются на всех!
Что не так?

ответ

24

Это будет делать все правильно:

 
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} неверны, как они ошибочно переименовать первое вхождение из .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) Он будет следовать символическим ссылкам в подкаталоги и ссылки на целевые файлы и переименовывать целевой файл, а не саму ссылку (поведение по умолчанию для поиска - это обработка самой символической ссылки, а не файла, на который указывает ссылка).

+0

Удивительно! Наконец-то решение, которое на самом деле работает. Спасибо миллион! – antred

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

Если какое-либо из названий каталогов или файлов может содержать пробелы, укажите оба параметра mv с помощью «. –

+1

@Lachlan: это само по себе не поможет. Вам нужно делать« находить ... »при чтении X 'вместо' for' (и делать цитату). Кроме того, у find должно быть свойство '-type f'. –

+1

[Почему вы не должны анализировать вывод ls (1)] (http: // mywiki .wooledge.org/ParsingLs) – slhck

3

Что плохого в том, что

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

+0

Спасибо, я должен был понять, что ... как-то ... Любое решение, которое еще не было упомянуто? – Pepijn

0

Он нуждается в рекурсии:

#!/bin/bash 

function walk_tree { 
    local directory="$1" 
    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 "." 
1

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

#!/bin/bash 

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

Баш скрипт для переименования расширения файлов обычно

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

Кредиты aps2012.

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

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

Люблю это, он отлично работает , и это быстро. –