简体   繁体   中英

How to rename all .jpg files in all subdirs which contains dash in linux?

I have subfolders with dashes (example subdir with name cd ). I need to rename all .jpg files with all subdirs, any tips how to do it?

I've tried many option, but nothing helped (I think because my subfolders contains dashes - )

$RANDOM can get you collisions. Let's use the md5 checksum hashes instead since they're random-looking yet determined by the content (meaning the only collisions will be when you have identical files anyway).

while IFS= read -r -d '' file; do
  mv "$file" "${file%/*}/$( md5sum "$file" |awk '{print $1}' )".jpg
done < <(find . -name '*.jpg' -print0)

This takes the md5 checksum of each file's contents and renames the file to it, preserving the directory structure and a trailing .jpg

This looks a bit ugly due to needing to preserve spaces.

Running while IFS= loops over contents with no input field separator ( $IFS ). Each iteration calls read -r -d '' file , which reads in content delimited by a null character while ignoring backslash escapes and stores entries in a variable called $file .

Skipping to the end of the loop, you can see it iterating on the null-terminated output of a find command that looks for files named *.jpg . This is performed via Bash process substitution in order to prevent scoping issues with a subshell created by a standard pipe (more detail can be found in BashFAQ/020 , which I adapted for this problem).

Inside the loop, we have the actual rename action, which uses command substitution to run md5sum on the file and then clean it up with awk (which is told to print only the first field, which is the checksum). The directory structure is preserved by parameter expansion , where ${file%/*} strips the last slash and all trailing non-slash characters so we can append the hash and then .jpg to the new file name. (This is the same as $(dirname "$file") but without the system call.)

If you really want random numbers and you don't care about collisions, replace $( md5sum "$file" |awk '{print $1}' ) with $RANDOM . If you give mv the -i option, it will prompt you in the event of a collision in the same directory.

This will not work in POSIX shells or other basic shells due to nonstandard flags in read and the process substitution. You can probably use mkfifo and/or xargs -0 to work around that, but that's not going to be easy.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM