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 files then
$ 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 2The 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 result Sorry 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 directory The 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.in Previous 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 3The 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.