问题
I know there are a lot of things like this around, but either they don't work recursively or they are huge.
This is what I got:
find . -name "*.so" -exec mv {} `echo {} | sed s/.so/.dylib/` \;
When I just run the find part it gives me a list of files. When I run the sed part it replaces any .so with .dylib. When I run them together they don't work.
I replaced mv with echo to see what happened:
./AI/Interfaces/C/0.1/libAIInterface.so ./AI/Interfaces/C/0.1/libAIInterface.so
Nothing is replaced at all!
What is wrong?
回答1:
This will do everything correctly:
find -L . -type f -name "*.so" -print0 | while IFS= read -r -d '' FNAME; do mv -- "$FNAME" "${FNAME%.so}.dylib" done
By correctly, we mean:
1) It will rename just the file extension (due to use of ${FNAME%.so}.dylib
). All the other solutions using ${X/.so/.dylib}
are incorrect as they wrongly rename the first occurrence of .so
in the filename (e.g. x.so.so
is renamed to x.dylib.so
, or worse, ./libraries/libTemp.so-1.9.3/libTemp.so
is renamed to ./libraries/libTemp.dylib-1.9.3/libTemp.so
- an error).
2) It will handle spaces and any other special characters in filenames (except double quotes).
3) It will not change directories or other special files.
4) It will follow symbolic links into subdirectories and links to target files and rename the target file, not the link itself (the default behaviour of find is to process the symbolic link itself, not the file pointed to by the link).
回答2:
for X in `find . -name "*.so"`
do
mv $X ${X/.so/.dylib}
done
回答3:
A bash script to rename file extensions generally
#/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
Credits to aps2012.
Usage
- Create a file e.g. called
ext-rename
(no extension, so you can run it like a command) in e.g./usr/bin
(make sure/usr/bin
is added to your$PATH
) - run
ext-rename [ext1] [ext2]
anywhere in terminal, where[ext1]
is renaming from and[ext2]
is renaming to. An example use would be:ext-rename so dylib
, which will rename any file with extension.so
to same name but with extension.dylib
.
回答4:
What is wrong is that
echo {} | sed s/.so/.dylib/
is only executed once, before the find
is launched, sed
is given {}
on its input, which doesn't match /.so/
and is left unchanged, so your resulting command line is
find . -name "*.so" -exec mv {} {}
回答5:
if you have Bash 4
#!/bin/bash
shopt -s globstar
shopt -s nullglob
for file in /path/**/*.so
do
echo mv "$file" "${file/%.so}.dylib"
done
回答6:
He needs recursion:
#!/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 "."
来源:https://stackoverflow.com/questions/2171966/bash-rename-extension-recursive