0

I have a directory with several thousand subdirectories inside (no subdirectories within those subdirectories however), and I need to flatten the contents of only some of the subdirectories, so basically bringing the contents of those directories to the root directory.

But I can't do that with all the subdirectories, and the ones which I can't flatten have multiple files in them.

Any way to do this automatically? Python script, perl script, bash, or whatever? I really, really, really don't want to have to do this by hand...

  • Generally speaking, perhaps. ;) Do you have programmable criteria for determining if a directory is to be flattened? – lurker Jul 16 '13 at 13:40
  • Like I said, the directory has to be flattened if there is only one file within it. I don't know if that is programmable criteria... – Tamara Macadam Jul 17 '13 at 09:56
  • Thanks for clarifying. Your original problem statement says, "...the ones which I can't flatten have multiple files in them" (i.e. if a folder has multiple files, it is not flattened") which does *not* imply that every folder with one file is flattened (if a folder has one file, it is flattened). So your additional comment helps. – lurker Jul 17 '13 at 10:56

1 Answers1

0

Something like this, in bash (foo represents the directory you want to flatten):

for x in foo/*
do
    COUNT=`ls -1 "$x" | wc -l`

    if ([ -d "$x" ] && (test $COUNT -le 1))
    then
        if test $COUNT -eq 1; then
            mv "$x"/* $1
        fi
        rmdir "$x"
    fi
done

This will also remove an empty subdirectory from foo.

You can also put this into a shell script file and use $1 as the directory name:

# Exit it a directory name isn't given

if [ "$1" = "" ] ; then
    echo "Usage: $0 directory"
    echo "Flattens directory"
    exit
fi

for x in "$1"/*
do
    COUNT=`ls -1 "$x" | wc -l`

    if ([ -d "$x" ] && (test $COUNT -le 1))
    then
        if test $COUNT -eq 1; then
            mv "$x"/* "$1"
        fi
        rmdir "$x"
    fi
done

You can put that into a file called flatten then run sh flatten foo to flatten the directory foo. Or, chmod +x flatten and run ./flatten foo. Ultimately, if you use it a lot over time, you can move it to a directory that's in our PATH so you can just type flatten foo. What I have is a bin file in my home directory on Linux where I put my own tools I want when I'm logged in, and I put my ~/bin in my PATH (set in the bash profile).

lurker
  • 56,987
  • 9
  • 69
  • 103
  • When I try to run that, it looks like it's trying to remove directories from the root directory of the entire system... – Tamara Macadam Jul 18 '13 at 02:32
  • In my first sentence I say, "$1 represents the directory you want to flatten". You have to set `$1` to the directory you want. If you put this into a shell script file, say called `foo`, then you could run `foo my_dir`. I've edited the answer to make that very clear. – lurker Jul 18 '13 at 02:45
  • Okay, when I try to run it now, it fails because it doesn't seem to be able to support directory names with multiple words in them, and instead brings up a bunch of errors like: `ls: This: no such file or directory` `ls: is: no such file or directory` `ls: a: no such file or directory` `ls: test: no such file or directory` `./foo: line 13: [: too many arguments` Am I doing something stupid? – Tamara Macadam Jul 18 '13 at 09:22
  • @user2587581, no you didn't do anything stupid. I neglected to quote the path name for `$x` to deal with embedded spaces. I've revised it. – lurker Jul 18 '13 at 10:45
  • Awesome, it now works perfectly. The only weird thing is that it said that some directories were not empty while ignoring others, and there wasn't any pattern at all. But that happened to only 7 directories, and I had over 2,500 to work with, plus it told me which directories weren't empty so it was super easy to clean up. Thanks! – Tamara Macadam Jul 18 '13 at 11:58
  • @user2587581 cool. I'd like to understand the two failure cases a little better. That would imply that the `rmdir` occurred on a non-empty directory, but I would expect it to be empty based upon the logic. You don't have any hidden files, do you (names start with a `.`)? And by ignoring, do you mean in some cases there was a singleton file, but it didn't flatten? – lurker Jul 18 '13 at 12:30