简体   繁体   中英

How to move many files in multiple different directories (on Linux)

My problem is that I have too many files in single directory. I cannot " ls " the directory, cos is too large. I need to move all files in better directory structure.

I'm using the last 3 digits from ID as folders in reverse way.

For example ID 2018972 will gotta go in /2/7/9/img_2018972.jpg .

I've created the directories, but now I need help with bash script. I know the IDs, there are in range 1,300,000 - 2,000,000 . But I can't handle regular expressions.

I wan't to move all files like this:

/images/folder/img_2018972.jpg -> /images/2/7/9/img_2018972.jpg

I will appreciate any help on this subject. Thanks!

EDIT : after explainations in comments the following assumptions exists:

  • filenames are in the form of img_<id>.jpg or img_<id>_<size>.jpg
  • the new dir is the reverse order of the three last digits of the id

using Bash:

for file in /images/folder/*.jpg; do 
    fname="${file%.*}"      # remove extension and _<size>
    [[ "$fname" =~ img_[0-9]+_[0-9]+$ ]] && fname="${fname%_*}"

    last0="${fname: -1:1}"  # last letter/digit
    last1="${fname: -2:1}"  # last but one letter/digit
    last2="${fname: -3:1}"  # last but two letter/digit

    newdir="/images/$last0/$last1/$last2"
    # optionally check if the new dir exists, if not create it
    [[ -d "$newdir" ]] || mkdir -p "$newdir"

    mv "$file" "$newdir"
done

if * can't handle it (although I think * in a for loop has no limits),
use find as suggested by @Michał Kosmulski in the comments

while read -r; do 
    fname="${REPLY%.*}"     # remove extension and _<size>
    [[ "$fname" =~ img_[0-9]+_[0-9]+$ ]] && fname="${fname%_*}"

    last0="${fname: -1:1}"  # last letter/digit
    last1="${fname: -2:1}"  # last but one letter/digit
    last2="${fname: -3:1}"  # last but two letter/digit

    newdir="/images/$last0/$last1/$last2"
    # optionally check if the new dir exists, if not create it
    [[ -d "$newdir" ]] || mkdir -p "$newdir"

    mv "$REPLY" "$newdir"
done < <(find /images/folder/ -maxdepth 1 -type f -name "*.jpg")
find /images/folder -type f -maxdepth 1 | while read file
do
filelen=${#file}
((rootn=$filelen-5))
((midn=$filelen-6))
((topn=$filelen-7))
root=${file:$rootn:1}
mid=${file:$midn:1}
top=${file:$topn:1}
mkdir -p /images/${root}/${mid}/${top}
mv $file /images/${root}/${mid}/${top}
done

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