0

I have folders of files with uppercase and lowercase filenames in Windows system.

For filenames starting with "a" or "A" are stored in either folder "A", or "a". All filenames starting with "b" or "B" are stored in either folder "B", or "b". etc

Currently folder names may be either uppercase "A" or lowercase "a" randomly.

Now, my task is to move these folders and files into Linux and separate the files into different folders according to uppercase and lowercase directory names & filenames. (e.g. atF0Gxx file put under "a" folder, while A0p9xxx file put under "A" folder, and similarly for b, B, c, C, d, D... z, Z)

If not doing manually for each files and folders, any solution please?

Files with a mix of uppercase and lowercase filenames

3 Answers 3

1

With zsh:

autoload -Uz zmv
mkdir -p {a..z} {A..Z}
zmv '[a-zA-Z]/(([a-zA-Z])*)' '$2/$1'

Would run mv -- x/Xwhatever X/Xwhatever for each file, skipping the mv calls for files that are already in the right directory. Add a -n option to zmv to only see what it would be doing without actually doing it.

1

Less elegant than zmv, but a simple for-loop is sufficient:

#!/bin/bash
for letter in {a..z} {A..Z} ; do
  mkdir /path/to/dest/$letter
  mv /path/to/source/*/${letter}?* /path/to/dest/$letter
done
4
  • Nice and simple! Note, however, that this will fail if you have a file named b since that won't allow you to create a directory named b. So if any of the first characters already exists as a file, this will fail.
    – terdon
    Commented Sep 20, 2021 at 11:36
  • @terdon Well, I strongly assumed dest to be an empty folder and different from source. Nevertheless, if I correctly interpret OP's question, files are already in directories a or A on the source system. The problem really lies with single-letter files which are not covered by ${letter}?*. (but it source really is already in directories, ${letter}* would work, too)
    – FelixJN
    Commented Sep 20, 2021 at 11:42
  • Ah. You may very well be right about the dir names. I just tried a similar approach (the first in my answer) in a directory where I happened to already have files named a and b, so I noticed the possible issue. That won't be a problem if the target dirs already exist though, you're absolutely right.
    – terdon
    Commented Sep 20, 2021 at 11:46
  • @terdon Thinking about "windows source", however, it popped into my mind that (by default) ntfs is not case sensitive. That would mean either a or A exist, never both.
    – FelixJN
    Commented Sep 20, 2021 at 11:48
0

A slightly more efficient version that only goes through the letters and numbers that are actually present:

for file in *; do
    if [[ ! -d "$file" ]]; then
        firstLetter=${file:0:1}
        mkdir -p "$firstLetter"
        mv -- "$file" "$firstLetter"/
    fi
done 

However, this will fail if you have a file with the same name as one of the directories. For example, a file named a won't allow you to create a directory also named a. To get around this, you can do:

tmpDir=$(mktemp -p "." -d)
for file in *; do
    if [[ ! -d "$file" ]]; then
      firstLetter=${file:0:1};
      ## If a file exists with this name
      if [[ -e "$firstLetter" && ! -d "$firstLetter" ]]; then
        ## move the file to the tmp dir and update the value
        ## of the $file variable to point to it
        mv -- "$file" "$tmpDir"
        file="$tmpDir/$file"
      fi
      mkdir -p "$firstLetter";
      mv -- "$file" "$firstLetter"/;
    fi
done
# $tmpDir should be empty by now
rmdir "$tmpDir"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .