Quote:
1) Find all files (-type f) with pattern *.jpg (-iname "*.jpg") (Used " to ensure you have full file name including spaces?) then print to Stdout
2) Piped that to a while loop (while ; do ..... done)
3) In the while loop read until no file name(read -d $'\0') ('\0' Null character?)
4) Take filename and put into variable filename
|
Mostly, yes. Just for reference while I explain what I did:
Code:
find ${SOURCE_DIR} -type f -iname "*.jpg" -print0 | while read -d $'\0' filename ; do
...
done
'-type f' -- only match actual files
'-iname "*.jpg"' -- case insensitive match. Find any name that ends with .jpg (e.g. .jpg, .JPG, or any case-combination)
The double quotes around the *.jpg is simply habit. It's born out of frustration dealing with unanticipated/unexpected wildcard expansion. The double quotes just make sure the shell keeps its grubby hands off. The space-handling is done through other means.
'-print0' -- part of the space-handling in the filenames. This tells find to put a NULL character after each matching filename rather than simply a newline. The NULL is used as a marker for the read command.
The results are sent to stdout, and stdout is piped into the read command.
"-d $'\0'" -- causes the read to store
everything up to a NULL character into the filename variable. Spaces, tabs, pretty much anything. Whereas without the --print0 and -d options to find and read respectively, the shell loop would separate the find output at any whitespace (space, tabs, newlines, etc.) causing the filename variable to have a piece of the actual path/file.
There are other ways of handling spaces (e.g. modify the IFS shell variable). So if my approach just feels too cryptic, you can probably find another approach that sits better with you.
Quote:
5) Convert spaces to _ using sed and put into variable removeSpaces
- why the echo?
|
The echo is necessary to give the filename to sed for processing. Sed will process information from a file or from standard input. Since the information that needs to be altered is in a variable, the echo is a pretty simple way of getting the variable's contents to standard output and then piped to sed.
You could do the same thing with parameter expansion (which I'm about to get to), and it would use the same basic syntax as sed. So, I'm guilty of falling into habit (again) for this step.
Quote:
6) create variable parentDirectory
- lost me here, does the %/* just capture the directory name.
|
Code:
parentDirectory=${removeSpaces%/*}
This is a special form of parameter expansion. So, this tells bash to take the contents of the variable removeSpaces and remove the
shortest part of the variable's contents that match the pattern after the '%'. Using the '%' makes the pattern matching start looking
from the end of the variable's contents (as opposed to the beginning).
The asterisk is a wildcard that matches anything, and the '/' is a literal slash. removeSpaces contains the full path to the file including the filename. If you remove everything from that full path after (and including) the last slash, you'll be left with the full path to the parent directory--the filename and the last slash will have been stripped.
Quote:
7) create variable newFilename
- Think I understand this line
|
Code:
newFilename="${DEST_DIR}/${parentDirectory##*/}.jpg"
Ok, another special form of parameter expansion here. Let me tackle that first. Using the double-hash mark (#) means to remove the
longest part of the variable's contents that match the pattern after the '##'. Also, using the hash form makes the pattern matching start
from the beginning of the variable's contents.
Again, the asterisk is a wildcard that matches anything, and the '/' is a literal slash. So everything in the variable up to and including the last slash is stripped off--which leaves the immediate parent directory name.
The rest of the assignment adds the destination directory to the front and the ".jpg" extension to the end.
You can read more about the special forms of parameter expansion by opening
man bash and searching for the parameter expansion section header (e.g. when inside the man page, type '/Parameter Expansion', press Enter, and hit 'n' (if necessary) until you reach the start of the section). You'll see the space-to-underscore style I alluded to before: ${parameter/pattern/string} as well as the discussion of the other forms I used.
Quote:
|
7) Then why the echo? Just to see output? == echo mv "\"${filename}\"" "\"${newFilename}\"" ==
|
This was to satisfy you that things are working. This is basically showing what the mv command would look like if it were uncommented.
As a rule of thumb, you should never trust your data to a script or program from the internet until you're sure it will work. There may be no malice involved, but a bug or an unanticipated environment quirk could cause data loss. Getting that data back could be easy (backups) or impossible depending on your situation.
Yup. And again, remove the '#' when you're comfortable it won't screw anything up.
EDIT: And one last thing--the double quotes around the arguments to the mv command are to guard against the spaces in the source directory and the destination directory (if any).