I'm hoping someone can help me, I'm looking for help with a bash script to move files by file extension from multiple directories, one directory deeper within their respective directories.
For example I have a 'Projects' directory, that has multiple directories within in it 'Project 001, Project 002, Project 003' and so on. I have '.JPG' files in those folders and want to put them in a 'JPG' folder within their respective project folder - how would I do this with a bash script as there are too many to do by hand?
To make matters more complicated some of those project folders already have 'JPG' folders in them, and some of those have some of the files already in them as duplicates, so I think I'd need to add an overwrite confirmation to it too based on filename.
I know a little bash, but this is a little over my head, so any help would be greatly appreciated.
Thanks,
/ Hami
This is using a CLI on Ubuntu Server 18.04 LTS, on a disk with thousands of directories with human filenames - spaces, parenthesis, and varied unicode character such as Japanese, and European. The names of the directories are varied, and have no particular formula.
Ideally, I'd like to go from this:
...to this:
You can do what you need with find
that searchers for all *.jpg
files and a simple helper script called by the -exec
option to find
to create the jpg
directory and move all .jpg
files into the new directory.
The helper script will simply get the absolute filename utilitzing readlink -f
and then using quick parameter expansion to trim the last /...
component from the absolute filename to obtain the full path. Then it is simply a matter of creating the jpg
directory at the end of the path and moving the file to the new directory.
Your helper script (I called it helper.sh
) could be:
#!/bin/sh
test -z "$1" && exit ## validate 1 argument given or exit
full=$(readlink -f "$1") ## get full filename
dir="${full%/*}" ## get full path
test "${full##*.}" = 'jpg' || exit ## test extension is jpg or exit
test -z "$dir" && dir="/" ## check if file was in / (root)
test -d "$dir/jpg" || mkdir -p "$dir/jpg" ## check/create jpg dir at end of path
mv "$full" "$dir/jpg" ## move file into new jpg dir
( note: after creating the helper script, make sure you make it executable with chmod +x helper.sh
)
Original Projects Directory Tree
$ tree Projects/
Projects/
├── Project_001
│ └── Image_001.jpg
├── Project_002
│ ├── Image_002.jpg
│ └── Image_003.jpg
└── Project_003
Your find
command operating on the Projects
directory calling the helper script for each file would be:
$ find Projects/ -type f -name "*jpg" -exec ./helper.sh '{}' \;
Resulting Projects Directory Tree
$ tree Projects/
Projects/
├── Project_001
│ └── jpg
│ └── Image_001.jpg
├── Project_002
│ └── jpg
│ ├── Image_002.jpg
│ └── Image_003.jpg
└── Project_003
Let me know if you have further questions.
Preserving Files Already In jpg Directory
Per-your additional comment, in order to preserve .jpg
files already within a jpg
directory under your Projects, all you need to do is add one additional check. If the last component of the path is already jpg
, just exit the helper, eg
test "${dir##*/}" = 'jpg' && exit ## if already in jpg dir, exit
Shown in context in helper.sh
:
test -z "$1" && exit ## validate 1 argument given or exit
full=$(readlink -f "$1") ## get full filename
dir="${full%/*}" ## get full path (trim last /*)
test "${dir##*/}" = 'jpg' && exit ## if already in jpg dir, exit
test "${full##*.}" = 'jpg' || exit ## test extension is jpg or exit
...
Original Projects Directory Tree (w/existing jpg)
$ tree Projects/
Projects/
├── Project_001
│ ├── Image_001.jpg
│ └── jpg
│ └── Image_000.jpg
├── Project_002
│ ├── Image_002.jpg
│ ├── Image_003.jpg
│ └── jpg
│ ├── Image_000.jpg
│ └── Image_001.jpg
└── Project_003
Resulting Projects Directory Tree
$ tree Projects/
Projects/
├── Project_001
│ └── jpg
│ ├── Image_000.jpg
│ └── Image_001.jpg
├── Project_002
│ └── jpg
│ ├── Image_000.jpg
│ ├── Image_001.jpg
│ ├── Image_002.jpg
│ └── Image_003.jpg
└── Project_003
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.