Skip to main content
added 732 characters in body
Source Link
muru
  • 77.9k
  • 16
  • 212
  • 318

While the general problem of identifying extensions is hard, you can clean up the script a bit:

  1. Tell find to only consider files with an extension: -iname '*.*'
  2. Use awk instead of cutting yourself:
  3. Use a script, and then tell find to exec that script.

Thus: a script called, say, move.sh:

#! /bin/bash
for i
do
    ext=/some/where/else/$(awk -F. '{print $NF}' <<<"$i")
    mkdir -p "$ext"
    mv "$i" "$ext"
done

Then run find thus:

find . -name '*.*' -type f -exec move.sh {} +

This has the problem that you can't rearrange within the folder, so you could use xargs:

find . -name '*.*' -type f -print0 > /tmp/temp
xargs -0 move.sh < /tmp/tmp

I'm not too sure of the efficiency involved, but another approach would be to get all the extensions, then move all the files involved in one swoop.

Something like:

find . -name '*.*' -type f -print0 | sed -z 's/.*\.//g' | sort -zu > /tmp/file-exts

This should get you a list of unique file extensions. Then our move.sh will look like:

#!/bin/bash
for i
do
    mkdir -p "$i"
    find . -name "*.$i" -type f -exec mv -t "$i" {} +
done

And we'll run it:

xargs -0 move.sh < /tmp/file-exts

I make quite a few assumptions in this post, such as sed and sort supporting -z (allowing them to work with the NUL-terminated lines that find and xargs thrive on).

While the general problem of identifying extensions is hard, you can clean up the script a bit:

  1. Tell find to only consider files with an extension: -iname '*.*'
  2. Use awk instead of cutting yourself:
  3. Use a script, and then tell find to exec that script.

Thus: a script called, say, move.sh:

#! /bin/bash
for i
do
    ext=/some/where/else/$(awk -F. '{print $NF}' <<<"$i")
    mkdir -p "$ext"
    mv "$i" "$ext"
done

Then run find thus:

find . -name '*.*' -type f -exec move.sh {} +

This has the problem that you can't rearrange within the folder, so you could use xargs:

find . -name '*.*' -type f -print0 > /tmp/temp
xargs -0 move.sh < /tmp/tmp

While the general problem of identifying extensions is hard, you can clean up the script a bit:

  1. Tell find to only consider files with an extension: -iname '*.*'
  2. Use awk instead of cutting yourself:
  3. Use a script, and then tell find to exec that script.

Thus: a script called, say, move.sh:

#! /bin/bash
for i
do
    ext=/some/where/else/$(awk -F. '{print $NF}' <<<"$i")
    mkdir -p "$ext"
    mv "$i" "$ext"
done

Then run find thus:

find . -name '*.*' -type f -exec move.sh {} +

This has the problem that you can't rearrange within the folder, so you could use xargs:

find . -name '*.*' -type f -print0 > /tmp/temp
xargs -0 move.sh < /tmp/tmp

I'm not too sure of the efficiency involved, but another approach would be to get all the extensions, then move all the files involved in one swoop.

Something like:

find . -name '*.*' -type f -print0 | sed -z 's/.*\.//g' | sort -zu > /tmp/file-exts

This should get you a list of unique file extensions. Then our move.sh will look like:

#!/bin/bash
for i
do
    mkdir -p "$i"
    find . -name "*.$i" -type f -exec mv -t "$i" {} +
done

And we'll run it:

xargs -0 move.sh < /tmp/file-exts

I make quite a few assumptions in this post, such as sed and sort supporting -z (allowing them to work with the NUL-terminated lines that find and xargs thrive on).

added 8 characters in body
Source Link
muru
  • 77.9k
  • 16
  • 212
  • 318

While the general problem of identifying extensions is hard, you can clean up the script a bit:

  1. Tell find to only consider files with an extension: -iname '*.*'
  2. Use awk instead of cutting yourself:
  3. Use a script, and then tell find to exec that script.

Thus: a script called, say, move.sh:

#! /bin/bash
for i
do
    ext=/some/where/else/$(awk -F. '{print $NF}' <<<"$i")
    mkdir -p "$ext"
    mv "$i" "$ext"
done

Then run find thus:

find . -name '*.*' -type f -exec move.sh {} +

This has the problem that you can't rearrange within the folder, so you could use xargs:

find . -name '*.*' -type f -print0 > /tmp/temp
xargs -0 move.sh < /tmp/tmp

While the general problem of identifying extensions is hard, you can clean up the script a bit:

  1. Tell find to only consider files with an extension: -iname '*.*'
  2. Use awk instead of cutting yourself:
  3. Use a script, and then tell find to exec that script.

Thus: a script called, say, move.sh:

#! /bin/bash
for i
do
    ext=/some/where/else/$(awk -F. '{print $NF}')
    mkdir -p "$ext"
    mv "$i" "$ext"
done

Then run find thus:

find . -name '*.*' -type f -exec move.sh {} +

This has the problem that you can't rearrange within the folder, so you could use xargs:

find . -name '*.*' -type f -print0 > /tmp/temp
xargs -0 move.sh < /tmp/tmp

While the general problem of identifying extensions is hard, you can clean up the script a bit:

  1. Tell find to only consider files with an extension: -iname '*.*'
  2. Use awk instead of cutting yourself:
  3. Use a script, and then tell find to exec that script.

Thus: a script called, say, move.sh:

#! /bin/bash
for i
do
    ext=/some/where/else/$(awk -F. '{print $NF}' <<<"$i")
    mkdir -p "$ext"
    mv "$i" "$ext"
done

Then run find thus:

find . -name '*.*' -type f -exec move.sh {} +

This has the problem that you can't rearrange within the folder, so you could use xargs:

find . -name '*.*' -type f -print0 > /tmp/temp
xargs -0 move.sh < /tmp/tmp
Source Link
muru
  • 77.9k
  • 16
  • 212
  • 318

While the general problem of identifying extensions is hard, you can clean up the script a bit:

  1. Tell find to only consider files with an extension: -iname '*.*'
  2. Use awk instead of cutting yourself:
  3. Use a script, and then tell find to exec that script.

Thus: a script called, say, move.sh:

#! /bin/bash
for i
do
    ext=/some/where/else/$(awk -F. '{print $NF}')
    mkdir -p "$ext"
    mv "$i" "$ext"
done

Then run find thus:

find . -name '*.*' -type f -exec move.sh {} +

This has the problem that you can't rearrange within the folder, so you could use xargs:

find . -name '*.*' -type f -print0 > /tmp/temp
xargs -0 move.sh < /tmp/tmp