2

I have 2500 archives name LposK.dat with L ranging from 1 to 10 and K ranging from 0.00 to 49.80. I need to move those that have the same K to a folder. I manage to do this using:

find . -name '*posK.dat' -exec mv {} ~/destination/K \;

But I have to manually change the value of K and repeat it multiple times. I was wondering if there's any way of using the index of a loop (eg: for loop) inside the find and mv commands so that I can write a script to do it.

Elias
  • 21

1 Answers1

1

To get the K from LposK.dat, if that string is in $name, we may do

k=${name%.dat}  # remove ".dat" suffix
k=${k##*pos}    # remove everything up to end of (the last) "pos"

This would work even if $name was a pathname like some/path/LposK.dat (and even if some/path contained the string pos), which is useful when we later plug it into find.

To move one file:

k=${name%.dat}
k=${k##*pos}

dest="$HOME/destination/$k"
mkdir -p "$dest" && mv "$name" "$dest"  # only move if mkdir did not fail

With find:

find . -type f -name '*pos*.dat' -exec sh -c '
    for name do
        k=${name%.dat}
        k=${k##*pos}

        dest="$HOME/destination/$k"
        mkdir -p "$dest" && mv "$name" "$dest"
    done' sh {} +

This would give the internal sh -c script a number of pathnames as arguments, and the script would iterate over these, moving each one into the correct subdirectory of $HOME/destination.

Related:


If your files are in a single subdirectory (the current directory), then you can do this even easier without find:

for name in ./*pos*.dat; do
    [ ! -f "$name" ] && continue  # skip non-regular files

    k=${name%.dat}
    k=${k##*pos}

    dest="$HOME/destination/$k"
    mkdir -p "$dest" && mv "$name" "$dest"
done
Kusalananda
  • 333,661