0

Got your attention with that title, didn't I? LOL.

Problem: I have a lot of folders that have a folder inside them, with files inside. I want to move the 2nd level files into the 1st level and do so without knowing their names.

Graphically, here's what I want:

Current:

new
└── temp
    ├── Folder1
    │   ├── SubFolder1
    │   │   └── SubTest1.txt
    │   └── Test1.txt
    ├── Folder2
    │   ├── SubFolder2
    │   │   └── SubTest2.txt
    │   └── Test2.txt
    └── Folder3
        ├── SubFolder3
        │   └── SubTest3.txt
        └── Test3.txt

Desired:

└── temp
    ├── Folder1
    │   ├── SubFolder1
    │   ├── SubTest1.txt
    │   └── Test1.txt
    ├── Folder2
    │   ├── SubFolder2
    │   ├── SubTest2.txt
    │   └── Test2.txt
    └── Folder3
        ├── SubFolder3
        ├── SubTest3.txt
        └── Test3.txt

If one wanted to get fancy, which I don't need to do as later in my script I remove empty files, but worth mentioning just in case I can learn even more:

└── temp
    ├── Folder1
    │   ├── SubTest1.txt
    │   └── Test1.txt
    ├── Folder2
    │   ├── SubTest2.txt
    │   └── Test2.txt
    └── Folder3
        ├── SubTest3.txt
        └── Test3.txt

I'm getting very close but I'm missing something and I'm sure it's simple/stupid. Here's what I'm running:

 find . -mindepth 3 -type f -exec sh -c 'mv -i "$1" "${1%/*}"' sh {} \;

Here's what that's getting me:

mv: './1stlevel/2ndlevel/test.rtf' and './1stlevel/2ndlevel/test.rtf' are the same file

Over on Stack Overflow, George got me closer by giving me:

find . -mindepth 4 -type f -exec mv {} ./*/* \; 

as well as:

mv ./*/*/*/* ./*/*

The mv command is the way to go, for sure, as it's cleaner and much, much faster. But, alas, while it works great with one folder, multiple folders makes it turn into this:

new
└── temp
    └── Folder3
        ├── Folder1
        │   ├── SubFolder1
        │   └── Test1.txt
        ├── Folder2
        │   ├── SubFolder2
        │   └── Test2.txt
        ├── SubFolder3
        ├── SubTest1.txt
        ├── SubTest2.txt
        ├── SubTest3.txt
        └── Test3.txt

So, I'm getting closer but not quite there. Any suggestions? Thank you in advance!

  • Beats me but the site I originally posted it on, someone jumped on me and said to put it here. So, sigh..... All I want is some bloody help. – Peter Apr 22 '18 at 23:14
  • 2
    I'm voting to close this question as off-topic because it has been cross-posted on SO while it shouldn't have. At the moment the question is upvoted there (with an already upvoted answer), downvoted here. – Kamil Maciorowski Apr 23 '18 at 5:18
  • 1
    Yea, while it probably belongs here on SU more than on SO, it's got a good answer there, and arguments about where things go become academic. Don't be disheartened please Peter, by this apparent squabbling: the purpose of different sites with different on-topics is to foment communities that are topic and powerful on those topics. So, don't cross-post in the future, please, but SU is probably the best place to start a question if you aren't sure where it should go because we are one of the more generic of the SE sites. – music2myear Apr 27 '18 at 22:45
  • 1
    Thank you, @music2myear, for your comment. I appreciate it, as I'll admit I was indeed disheartened by the whole situation. Fortunately, George got me a great answer, and G-Man another way to do it that also gave me a good tip on future troubleshooting. Betwixt the three of you, my faith has been restored. Take care! – Peter May 27 '18 at 21:29
1

You could use a for loop to simplify this. i used the dirname $tiem/.. to get one level up and the mindepth to limit the effect to one level.

localhost$ tree
.
└── temp
    ├── folder1
    │   ├── subfolder1
    │   │   └── file1
    │   └── test1.txt
    ├── folder2
    │   ├── subfolder2
    │   │   └── file2
    │   └── test2.txt
    └── folder3
        ├── subfolder3
        │   └── file3
        └── test3.txt

7 directories, 6 files
/tmp/foo/new

localhost$ for item in `find . -mindepth 4 -type f`; do echo $item `dirname $item`/..; done
./temp/folder1/subfolder1/file1 ./temp/folder1/subfolder1/..
./temp/folder3/subfolder3/file3 ./temp/folder3/subfolder3/..
./temp/folder2/subfolder2/file2 ./temp/folder2/subfolder2/..

After the move it becomes

localhost$ for item in `find . -mindepth 4 -type f`; do mv $item `dirname $item`/..; done
/tmp/foo/new
localhost$ tree
.
└── temp
    ├── folder1
    │   ├── file1
    │   ├── subfolder1
    │   └── test1.txt
    ├── folder2
    │   ├── file2
    │   ├── subfolder2
    │   └── test2.txt
    └── folder3
        ├── file3
        ├── subfolder3
        └── test3.txt

7 directories, 6 files
/tmp/foo/new

localhost$

Hope that helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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