Script to rename files
Please bear with me... I have some linux experience. But I'm stumped.
I have 500+ directories with a single file in each directory. I would like to rename each file in the directory with the directory name and move the file to another directory. I can do this manually, but there must be a script to to this. System Details: Fedora 14 Any help? |
You should be able to set up a simple bash script by using the ls command while you're in the directory containing the folders, and then cd into each dir and copy the file back. Try looking at some bash tutorials. ls will list the files and directories in a specific directory, and mv will move and/or rename files. For example, if I wanted to see all of the files in my home directory, I would type:
Code:
ls /home/USER Code:
mv /home/USER/name/name /home/USER/name Sorry if I'm not that much help to you, I don't program bash but it should be a fairly easy first project :) |
Perhaps I can help, but you need to flesh out the problem a little more.
How are the directories and files organized? Is there a single directory that all of them are under? For instance: /home/usera/myfiles /home/usera/myfiles/dir01/filename /home/usera/myfiles/dir02/filename /home/usera/myfiles/dir03/filename ... Do the filenames follow any sort of pattern? Do they all have the same name--just differentiated by the parent directory? When you say you want the directory added to the filename, which part of the directory? Just the parent directory? The full, absolute path? Since you can't include a '/' as part of a filename, what character would you like to use to separate the path component(s) from the filename? In a nutshell, it would probably be easiest to give an example of what your set up looks like as it stands now, and then show what you would like it to be after the script runs. |
jbigs12/Dark_Helmet thanx for the response,
The directory structure is as follows. /home/usera/myfiles /home/usera/myfiles/Kathy Johnson/image123.jpg /home/usera/myfiles/Fred Smith/image324.jpg /home/usera/myfiles/Bill Smith/image 657.jpg I would like to have. /home/usera/myfiles/new_Directory/Kathy_Johnson.jpg (For /home/usera/myfiles/Kathy Johnson/image123.jpg) /home/usera/myfiles/new_Directory/Fred_Smith.jpg (For /home/usera/myfiles/Fred_Smith/image324.jpg) The files are coming from a windows system hence the spaces. The only pattern is ..../Name/filename.jpg I have the ability to relocate the complete structure to a single drive(s) if that makes the script easier. The assistance is appreciated. |
Here is a possible solution based on that info.
Code:
#!/bin/bash You need to: (1) modify the values assigned to SOURCE_DIR and DEST_DIR to match your setup (2) make sure that DEST_DIR actually exists (i.e. use mkdir to create it if necessary) (3) make at least one dry-run and make sure the echo statements are "sane" This script will search for any file with a "jpg" extension beneath SOURCE_DIR. For any file found, the script will determine the new filename by (1) substituting underscores for spaces; (2) determining the immediate parent directory; and (3) adding a "jpg" extension to the parent directory name. Things that would cause the train to go off the tracks: multiple jpg files in the same directory or multiple subdirectories that share the same name (e.g. SOURCE_DIR/Kathy and SOURCE_DIR/somesub/Kathy). In the case of multiple files in one directory, subsequent jpg files would overwrite previous jpg files (because all files would share a common parent directory, and hence a single destination filename). Similarly, if multiple directories share the same name and each has a jpg file, the script would generate the same filename for each file and subsequent files would overwrite previous ones. Lastly, the script will not remove the directories that are emptied after the script runs. You'll need to do that manually if there is no other purpose for them. |
copy this script to /home/usera/myfiles and run it ;) (
Code:
#!/bin/bash |
Be cautious: mmhs's script does not handle filenames with spaces in them. Given that the subdrectories and some of the filenames themselves have spaces, that is a serious concern.
|
Ruby(1.9+)
Code:
#!/usr/bin/env ruby |
Dark_Helmet, thanx.
Let me understand (my learning) what you have done. ============ #!/bin/bash SOURCE_DIR=/home/usera/myfiles DEST_DIR=/home/usera/myfiles/new_Directory find ${SOURCE_DIR} -type f -iname "*.jpg" -print0 | while read -d $'\0' filename ; do removeSpaces=$( echo "${filename}" | sed 's@ @_@g' ) parentDirectory=${removeSpaces%/*} newFilename="${DEST_DIR}/${parentDirectory##*/}.jpg" echo mv "\"${filename}\"" "\"${newFilename}\"" # mv "${filename}" "${newFilename}" done =========== 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 5) Convert spaces to _ using sed and put into variable removeSpaces - why the echo? 6) create variable parentDirectory - lost me here, does the %/* just capture the directory name. 7) create variable newFilename - Think I understand this line 7) Then why the echo? Just to see output? == echo mv "\"${filename}\"" "\"${newFilename}\"" == 8) Actual move command Do have this right? There is no way I could have done this. Thank you very much. Sorry to ask again, but I like to learn mike g. |
Quote:
Code:
find ${SOURCE_DIR} -type f -iname "*.jpg" -print0 | while read -d $'\0' filename ; do '-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:
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:
Code:
parentDirectory=${removeSpaces%/*} 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:
Code:
newFilename="${DEST_DIR}/${parentDirectory##*/}.jpg" 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:
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. Quote:
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). |
Dark_Helmet, Thank you.
This is slick...... Works like a charm.... mike g. |
All times are GMT -5. The time now is 08:33 AM. |