Reputation: 21081
I've folder and file structure like
Folder/1/fileNameOne.ext
Folder/2/fileNameTwo.ext
Folder/3/fileNameThree.ext
...
How can I rename the files such that the output becomes
Folder/1_fileNameOne.ext
Folder/2_fileNameTwo.ext
Folder/3_fileNameThree.ext
...
How can this be achieved in linux shell?
Upvotes: 0
Views: 3090
Reputation: 21081
This solution from AskUbuntu worked for me.
Here is a bash script that does that:
Note: This script does not work if any of the file names contain spaces.
#! /bin/bash # Only go through the directories in the current directory. for dir in $(find ./ -type d) do # Remove the first two characters. # Initially, $dir = "./directory_name". # After this step, $dir = "directory_name". dir="${dir:2}" # Skip if $dir is empty. Only happens when $dir = "./" initially. if [ ! $dir ] then continue fi # Go through all the files in the directory. for file in $(ls -d $dir/*) do # Replace / with _ # For example, if $file = "dir/filename", then $new_file = "dir_filename" # where $dir = dir new_file="${file/\//_}" # Move the file. mv $file $new_file done # Remove the directory. rm -rf $dir done
chmod +x file_name
Folder/
../file_name
.Upvotes: 0
Reputation: 274532
Use a loop as follows:
while IFS= read -d $'\0' -r line
do
mv "$line" "${line%/*}_${line##*/}"
done < <(find Folder -type f -print0)
This method handle spaces, newlines and other special characters in the file names and the intermediate directories don't necessarily have to be single digits.
Upvotes: 2
Reputation: 753475
How many different ways do you want to do it?
If the names contain no spaces or newlines or other problematic characters, and the intermediate directories are always single digits, and if you have the list of the files to be renamed in a file file.list
with one name per line, then one of many possible ways to do the renaming is:
sed 's%\(.*\)/\([0-9]\)/\(.*\)%mv \1/\2/\3 \1/\2_\3%' file.list | sh -x
You'd avoid running the command through the shell until you're sure it will do what you want; just look at the generated script until its right.
There is also a command called rename
— unfortunately, there are several implementations, not all equally powerful. If you've got the one based on Perl (using a Perl regex to map the old name to the new name) you'd be able to use:
rename 's%/(\d)/%/${1}_%' $(< file.list)
Upvotes: 2
Reputation: 289495
This may work if the name is always the same, ie "file":
for i in {1..3};
do
mv $i/file ${i}_file
done
If you have more dirs on a number range, change {1..3}
for {x..y}
.
I use ${i}_file
instead of $i_file
because it would consider $i_file
a variable of name i_file
, while we just want i
to be the variable and file
and text attached to it.
Upvotes: 1