Replace a folder name using a contained file name
Andrew Mclaughlin
I have a thousand or so folders having random names. Every folder has at least one file with avi, mkv,srt or mp4 extension.
I intend to replace the random generated folder name by the first file name (without extension) contained on it. By the way the name of the files use to include () - and other strange characters.
The script should, in my opinion:
- Go into the folder
- Get the first name without extension
- Go out of the folder
- Rename the folder using the new name
- Recursive travel the folders as it may contain other subfolder
The 5th step may be override, though.
As I am a nerd in bash programming, I'd apreciate a hand. Can anyone help?
3 Answers
Given
$ tree
.
├── eYRlzR8Ibk
│ ├── Awnluslskl
│ │ └── ö, û, accnts.avi
│ ├── baz
│ └── xyz.mp4
└── wHKEWxFgIt └── foo bar.srt
3 directories, 4 filesthen
$ find . -mindepth 1 -depth -type d -execdir sh -c ' for d; do set -- "$d"/*.* [ -e "$1" ] || continue f="${1##*/}" mv -n -- "$d" "${f%.*}" done
' sh {} +resulting in
$ tree
.
├── foo bar
│ └── foo bar.srt
└── xyz ├── baz ├── ö, û, accnts │ └── ö, û, accnts.avi └── xyz.mp4
3 directories, 4 files 2 The script
Copy/paste the script in your text editor
Replace ~/test/testfolders3 in sourcedir variable by your directory name wich contains all the directories with files
Try it without mv $oldname $newname first time to see what should happen.
After editing you could just copy it from your text editor and past it in terminal window.
sourcedir=~/test/testfolders3
cd $sourcedir
files=$(find . -type f)
for f in $files do echo -e "0:Not modified file name:\t $f" bname=$(basename $f) # Get file's name without path to it filewe=$(echo $bname | sed 's/\.[^.]*$//') # Get file's name without extension echo -e "1:Filename without extension:\t $filewe" dir=$(dirname $f) # Get directory name where file is located echo -e "2:Parent file's directory:\t $dir" parfold=$(echo $(dirname $dir) | sed 's/.\///') # Get file's parent directory's parent directory name with stripped `./` preffix echo -e "3:Parent-parent stripped dir:\t $parfold" olddir=$(echo $dir | sed 's@.*/@@') # Get file's parent directory name without path to it (everything before the last `/` slash is stripped) oldname=$sourcedir/$parfold/$olddir # Get current file's parent directory name with full path echo -e "4:Old folder name:\t\t $oldname"; newname=$sourcedir/$parfold/$filewe # Set new file's parrent directory name with full path echo -e "5:New folder name:\t\t $newname" mv $oldname $newname # Renames folders done
find $sourcedir -type f # Shows resultSorry if it is not fully optimized. I'm not programmer. It's only a compilation of different answers I've found to write it. It took a lot of time, because of I do not do it frequently.
It does not check now if directory exists. So being renamed once by the first moved file's name it will just throw a message like this:
mv: cannot stat '/home/user/test/testfolders3/folders/lkjskd': No such file or directoryThe first moved file does not mean the first in alphabetical order.
Here's result of find $sourcedir -type f command execution:
/home/user/test/testfolders3/folders3/file3/file3.mp4
/home/user/test/testfolders3/folders3/file1/file1.avi
/home/user/test/testfolders3/folders3/file2/file2.mkv
/home/user/test/testfolders3/folders3/folders/file3/file3.mp4
/home/user/test/testfolders3/folders3/folders/file1/file1.avi
/home/user/test/testfolders3/folders3/folders/file2/file2.mkv
/home/user/test/testfolders3/folders2/soft/soft.ware
/home/user/test/testfolders3/folders2/soft/file1.avi
/home/user/test/testfolders3/folders2/inter/inter.pol
/home/user/test/testfolders3/folders2/inter/file3.mp4
/home/user/test/testfolders3/folders2/file2/file2.mkv
/home/user/test/testfolders3/folders2/file2/ser.seg
/home/user/test/testfolders3/folders2/folders/file3/file3.mp4
/home/user/test/testfolders3/folders2/folders/file1/file1.avi
/home/user/test/testfolders3/folders2/folders/file2/file2.mkv
/home/user/test/testfolders3/folders/kata/kata.ptx
/home/user/test/testfolders3/folders/kata/file1.avi
/home/user/test/testfolders3/folders/sinaps/sinaps.rtf
/home/user/test/testfolders3/folders/sinaps/file3.mp4
/home/user/test/testfolders3/folders/file2/file2.mkv
/home/user/test/testfolders3/folders/file2/tema.txt
/home/user/test/testfolders3/folders/file2/fan.inPrevious folders' names:
/home/user/test/testfolders3/folders3/kjakd/file2.mkv
/home/user/test/testfolders3/folders3/jafklsjdkl/file1.avi
/home/user/test/testfolders3/folders3/folders/kjakd/file2.mkv
/home/user/test/testfolders3/folders3/folders/jafklsjdkl/file1.avi
/home/user/test/testfolders3/folders3/folders/lkjskd/file3.mp4
/home/user/test/testfolders3/folders3/lkjskd/file3.mp4
/home/user/test/testfolders3/folders2/kjakd/file2.mkv
/home/user/test/testfolders3/folders2/kjakd/ser.seg
/home/user/test/testfolders3/folders2/jafklsjdkl/soft.ware
/home/user/test/testfolders3/folders2/jafklsjdkl/file1.avi
/home/user/test/testfolders3/folders2/folders/kjakd/file2.mkv
/home/user/test/testfolders3/folders2/folders/jafklsjdkl/file1.avi
/home/user/test/testfolders3/folders2/folders/lkjskd/file3.mp4
/home/user/test/testfolders3/folders2/lkjskd/inter.pol
/home/user/test/testfolders3/folders2/lkjskd/file3.mp4
/home/user/test/testfolders3/folders/kjakd/file2.mkv
/home/user/test/testfolders3/folders/kjakd/tema.txt
/home/user/test/testfolders3/folders/kjakd/fan.in
/home/user/test/testfolders3/folders/jafklsjdkl/kata.ptx
/home/user/test/testfolders3/folders/jafklsjdkl/file1.avi
/home/user/test/testfolders3/folders/lkjskd/sinaps.rtf
/home/user/test/testfolders3/folders/lkjskd/file3.mp4 3 The solution proposed by Steelworker (see above) worked perfectly, fast and smooth. A very clean and simple code. You guys are incredible. Thanks for your time and dedication. Best regards.