Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

When digging around in the advanced settings in Dropbox I lost a folder. I only discovered this about a month later. I managed to get this folder back from Dropbox however the file structure of the subfolders have changed dramatically. The current folder now contains two versions of each original subfolder. Currently it looks like this:

folder
  /folder1
    /folder11
      /folder111
      /Folder111
       /file1111
       /file1112
       /file1113
    /Folder11
      /file111
      /file112
    /folder12
    /Folder12
  /folder2
  /folder3  

So I have lowercase subfolders and I have BumpyCase subfolders. The lowercase subfolders contain subsubfolders and the BumpyCase subfolders contain files. The subsubfolders again contain a lowercase and a BumpyCase version of their respective subfolders. And this story goes on for several levels deep.

Fortunately there is no duplication in files, only in folders (same letters but different casing). So on each level I need to merge folders which differ only in the casing of names. And to do this correctly I need to start at the deepest level and work myself up to the top level folder.

I want everything to go into the CamelCase directories.

The partition where the data is is an Ext4 partition. I have access to several NTFS partitions.

Is there a handy Linux command/tool or someone with an idea for a script which could accomplish this? I'm already very happy that I got my stuff back, but the current structure is a big inconvenience.

share|improve this question
    
Do you want to merge the files into the lower or CamelCase directories? You didn't say what you ultimately wanted. –  slm Oct 10 '13 at 13:51
    
Do you have access to a VFAT partition? You might be able to do something clever if so since VFAT is case insensitive. –  terdon Oct 10 '13 at 17:22
    
I want everything to go into the CamelCase directories. The partition where the data is is an Ext4 partition. I have access to several NTFS partitions. –  cfbaptista Oct 10 '13 at 19:44
    
Merging to lowercase directories would be easier. Do you only ever have one camelcase directory per lowercase equivalent? If not, how do you decide between FoobAr and fOOBAr? –  Gilles Oct 10 '13 at 21:36
    
No it differs. The actual data is what I have collected for my uni over the years. The top level folder is University and this has as subfolders the 1st until 5th year. And these folders contain a folder per course and those folders contain folders like Old exams, Lecture slides, Assignments and Hand-outs. But everything is good now. I fiddled around a little bit more with Dropbox and I managed to get the folder in its original from directly from Dropbox. –  cfbaptista Oct 10 '13 at 22:19

1 Answer 1

All commands start from the toplevel directory and assume that you have no newlines in file names. I assume GNU tools (Linux or Cygwin). Warning, this is all untested code, typed directly into the browser.

It's fairly easy to merge all directories to lowercase. One approach is to recurse over all directories and merge them into their lowercase counterpart. Do the traversal depth first so that when you merge two directories, their content is already normalized.

find . -depth -name '*[[:upper:]]*' -type d -execdir sh -c '
  source=$0
  target=$(echo "$source" | tr "[:upper:]" "[:lower:]")
  if [ "$source" != "$target" ]; then  # need to rename or merge
    if [ -d "$target" ]; then
      # merge $source (mixed- or uppercase) into $target (lowercase)
      find "$source" -mindepth 1 -maxdepth 1 -exec mv -bt "$target" {} +
      rmdir "$source"
    else
      mv "$source" "$target"
    fi
  fi
' {} \;

If you want to merge from lowercase to mixed case, you need to determine the mixed-case directory corresponding to each lowercase directory. The following snippet picks an arbitrary mixed-case directory if there is more than one.

find . -depth ! -name '*[[:upper:]]*' -type d -execdir sh -c '
  source=$0
  target=$(find . -maxdepth 1 -iname "$source" -not -name "$source" -print -quit)
  if [ -n "$target" ]; then …
  fi
' {} \;
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.