Easiest way to move contents of all subfolders into parent folder

Discussion in 'Other Operating Systems' started by shredder, Oct 23, 2018.

  1. shredder

    shredder Member

    Joined:
    Dec 26, 2001
    Messages:
    11,547
    Location:
    Dec 27, 1991
    Ubuntu 18. Everyday home usage.

    A simple little process. How can you best automate it?

    1. A script (nice)? Could do this easily in DOS 25 years ago, with a bat. Help me create the linux version.

    2. A GUI extension (nicer)? Could do this easily in Windows 10 or 20 years ago (as in, somebody else had created the right-click GUI extension, and you could easily obtain and install it). Can we add this to Ubuntu?

    EXAMPLE OF PROCESS:

    Before:
    Code:
    PARENT_FOLDER/SUB1/file1.txt
                      /file2.wtf
                      /otherthing.docxxx
    PARENT_FOLDER/THING/spreadsheetoftheuniverse.xls
                       /whatever.txt
    PARENT_FOLDER/XTREEGOLD/xtg.bat
                           /yolo.txt
    ...etc...
    
    After:
    Code:
    PARENT_FOLDER/file1.txt
                 /file2.wtf
                 /otherthing.docxxx
                 /spreadsheetoftheuniverse.xls
                 /whatever.txt
                 /xtg.bat
                 /yolo.txt
    ...etc... 
    I could Google this and figure it out myself, but thought it might be a bit of fun (and educational) for the experts here to discuss the best alternatives for solving a simple file process in modern Linux.
     
    Last edited: Oct 23, 2018
  2. BAK

    BAK Member

    Joined:
    Jan 7, 2005
    Messages:
    1,023
    Location:
    MornPen, VIC
  3. OP
    OP
    shredder

    shredder Member

    Joined:
    Dec 26, 2001
    Messages:
    11,547
    Location:
    Dec 27, 1991
    Thanks for your input BAK. Your 2009 link is a good starting point.

    I don't want to have to type that long technical sentence every time. Let's make it so I only have to jump to terminal in a given folder, and run a three letter command (let's call it "stp", short for "subfolders to parent") to execute the process.

    I also encourage further discussion of the other questions in my post, and other alternatives, in the vein of the principle stated:
    For example, once we have the 3 letter script sorted, we can move on to the GUI implementation.
     
    Last edited: Oct 23, 2018
  4. BAK

    BAK Member

    Joined:
    Jan 7, 2005
    Messages:
    1,023
    Location:
    MornPen, VIC
    Have a look at "alias", it should achieve this for you. You can use it to create aliases for commands. You could also create a script that runs that command, and name it "stp" and place it in a folder that your shell interprets as containing binaries, such that when you type "stp" it runs that script.
     
  5. Statitica

    Statitica Member

    Joined:
    Dec 29, 2009
    Messages:
    3,191
    Location:
    Lae, Morobe, PNG
    Couldn't this be done with something like:
    Code:
    # mv would work just as well, if not better for the OP's intent
    cp -Ruv * ../
    ?

    EDIT: I guess it depends on the start point (mine assumes you are in the sub-folder when you run the command). You could mess around with for loops, or write a python script and make it run, but to be honest BAK's solution is probably the simplest.

    Which file browser are you using? Thunar (xfce) has context sensitive scripting enabled by default, and to most of the others you can add an extension called "filemanager-actions" or "caja-actions" in MATE. You don't need to worry about the CLI, you just put your command in behind an alias, right click on your folder and go for gold.
     
    Last edited: Jan 23, 2019
    shredder likes this.
  6. ORiGINAL

    ORiGINAL Member

    Joined:
    Sep 4, 2002
    Messages:
    661
    Location:
    TAS

    > alias stp='find . -mindepth 2 -type f -print -exec mv {} . \;'

    There you go, 3 letter command to perform the function.

    The whole idea of doing these things from the cli is to be fast, gui's make that moot.
     
  7. cvidler

    cvidler Member

    Joined:
    Jun 29, 2001
    Messages:
    12,198
    Location:
    Canberra
    sounds homeworky.

    how you gonna handle name conflicts?
    silent overwrite (and then overwrite older only, or any)? silent fail? silent rename? prompt the user?
     
  8. OP
    OP
    shredder

    shredder Member

    Joined:
    Dec 26, 2001
    Messages:
    11,547
    Location:
    Dec 27, 1991
    Good to see the various approaches. Many good tips and info in here, thanks. :thumbup: :thumbup:
    But if your hand is already on the mouse, then it takes an action to open the terminal (not to mention moving your hands to the keyboard) - redundant movements that could have been spent executing the actual task.

    (provided the gui is set up to execute that task, then you'll be done in the GUI before you've even started typing in the CLI - therefore the speed win is with the GUI, is it not?)
    I wish I was still young and carefree enough to be a student! :lol:

    These days, my homework is literally just "stuff I do at home in my spare time".

    Including, very very slowly moulding my Ubuntu install to suit my habits.
     
    Last edited: May 2, 2019
  9. ORiGINAL

    ORiGINAL Member

    Joined:
    Sep 4, 2002
    Messages:
    661
    Location:
    TAS
    I'm rarely in a GUI on my linux hosts, most don't even have one installed, especially if performing tasks such as moving files around like this. Obviously personal preference.
    If you're already in a file manager in a gui then would select all > dragging the files up one level not be just as fast as a sub menu?

    And, even quicker to hit ALt + F2 and type stp if you are in a gui.
     
    Last edited: May 3, 2019
  10. Quadbox

    Quadbox Member

    Joined:
    Jun 27, 2001
    Messages:
    6,218
    Location:
    Brisbane
    I cant remember the last time I didnt have a terminal open lol
     
  11. OP
    OP
    shredder

    shredder Member

    Joined:
    Dec 26, 2001
    Messages:
    11,547
    Location:
    Dec 27, 1991
    This is an everyday home desktop, for home users. 90% of the time is spent in Chrome, with only one monitor on.

    Not having a GUI even installed, or keeping a terminal window always open, aren't really practical parts of that (my) world in that context.

    --

    "Select all > dragging the files up one level" will not batch several folders at once, which is the whole point.

    --

    Your suggestion to set up alias stp='find . -mindepth 2 -type f -print -exec mv {} . \;' and then use ALT+F2 and run stp simply results in "Command not found". I'm also not convinced it would execute the command in the currently focused file manager GUI window? Could be messy if not.

    --

    So far, there isn't a working method that beats having the 'find ... command set up as a right-click option for instant two-click execution in the current file manager GUI window.

    Given that I'm in the GUI as a start point, with a hand on the mouse - invoking the terminal simply cannot provide a faster method. Right? Instant two-click execution. In this context, why bother to have to type stuff each time, no matter how short?
     
    Last edited: May 3, 2019
  12. GumbyNoTalent

    GumbyNoTalent Member

    Joined:
    Jan 8, 2003
    Messages:
    7,533
    Location:
    Briz Vegas
    All I read is, I'm unwilling to lean how to use Linux efficiently and want someone to show me how to do it using an already scripted GUI. you have been given a solution you just can't or are unwilling to educate yourself enough to use that knowledge to make the task automated to your liking, so I suggest you continue to do it manually using the GUI because that is all you are willing to do, I know which one I would use and it doen't involve a GUI and will get the job done in a pooftenth of the time using a GUI.

    As for stp not being found, thats easy to fix with google as you obviously have not set up the alias stp.

    EDIT -

    /some_place/
    /some_place/a
    /some_place/a/aa

    cd /some_place/a
    mv * ..

    ^ that will place all contents of /some_place/a (including all child directories like aa) into /some_place

    then remove /some_place/a because it is empty
    rm -rf /some_place/a

    rinse and repeat for all directories.

    or learn recusive find command.
     
    Last edited: May 3, 2019
  13. OP
    OP
    shredder

    shredder Member

    Joined:
    Dec 26, 2001
    Messages:
    11,547
    Location:
    Dec 27, 1991
    They say you hear what you want to hear.

    1. I said in the OP that I can easily Google it myself. This thread was for discussion purposes, to see a cross sections of methods used by various people. Therefore your statement "want someone to show me how to do it" is patently wrong. No worries, I accept your tacit retractment.

    2. The two-click solution I've implemented is more efficient than any Terminal solution provided. Therefore your statement "I'm unwilling to lean[sp] how to use Linux efficiently.." is patently wrong. I've shown the exact opposite, finding and setting up the most efficient solution for my circumstance. No worries, I accept your tacit retractment.
    Was the bit where I obviously did not set up the alias stp, the bit where I went alias stp='find . -mindepth 2 -type f -print -exec mv {} . \;' ? or did you just not bother to read most of the thread, in your mindless charge to criticise?
    If you bothered to read the OP, you'd have seen "Could do this easily in DOS 25 years ago, with a bat". You'd then realise the obvious that it's pointless to tell such a person about basic "cd" and "mv" type commands. I'm not looking for the longform way of doing things.
    We obviously have covered that near the beginning of the thread (post #2, if you can make it that far...), and further, if you bothered to read it, instead of your mindless charge to criticise.
     
    Last edited: May 3, 2019
  14. gdjacobs

    gdjacobs Member

    Joined:
    Apr 3, 2007
    Messages:
    1,441
    Location:
    MB, Canada
    You can also script it in pure BASH along these lines:
    Code:
    #! /bin/bash
    GLOBIGNORE=". .."
    # Ignore the current and parent directory
    
    for i in * .*; do
        if [ -d "$i" ]; then
            pushd $i
            mv -i * .* ..    # Use interactive to avoid clobbering duplicate names
            popd
            rmdir $i
        fi
    done
    
    Notice that the find one liner above (or an equivalent chaining into xargs) is shorter and probably faster.
     
    shredder likes this.
  15. GumbyNoTalent

    GumbyNoTalent Member

    Joined:
    Jan 8, 2003
    Messages:
    7,533
    Location:
    Briz Vegas
    You definition of discussion is NO to accepted ways to do complex things in Linux, that is not a discussion.

    No re=read your first post you want to collaspe all directores into the parent, your solution would still leave you with child directories in the parent, when a recurrsive loop would collapse childern as well, but WTF would I know from doing this shit for 40 years.

    Yes which is why I said your GUI solution while not a solution is your best bet because your not interested in finding the best solution, so why ask?

    No I read the whole thread, my opinion of you and your request hasn't changed.
     
  16. gdjacobs

    gdjacobs Member

    Joined:
    Apr 3, 2007
    Messages:
    1,441
    Location:
    MB, Canada
    Let me modify my solution with recursion.

    Code:
    #!/bin/bash
    GLOBIGNORE=". .."
    # Ignore the current and parent directory
    
    descend() {
        for i in * .*; do
            if [ -d "$i" ]; then
                pushd "$i"
                descend
                mv -i * .* ..    # Use interactive to avoid clobbering duplicate names
                popd
                rmdir "$i"
            fi
        done
    }
    
    descend "$PWD"
    
    Find will still be faster as it's tight, compiled code. BASH has overhead.

    Hopefully you don't have too many clashing file names.
     
    Last edited: May 3, 2019
  17. OP
    OP
    shredder

    shredder Member

    Joined:
    Dec 26, 2001
    Messages:
    11,547
    Location:
    Dec 27, 1991
    Rubbish, Grumps. It's not my problem if you can neither see nor accept rational discussion of the options and the context of my workflow.
    Thanks for arguing with me about what I want to do. No, really. Your 40 year knowledge might be useful if you weren't such a Grump charging in to White Knight the CLI, disrespecting anyone who dares to explore options.
    Wrong. I've gratefully taken in all the information posted, and learned some useful things. No worries, I accept your retraction.
    That's because you're a Grump.

    GrumpyNoTalent.
     
    Last edited: May 4, 2019
    GumbyNoTalent likes this.
  18. eixt

    eixt Member

    Joined:
    Apr 9, 2003
    Messages:
    1,281
    Location:
    Canberra
    nevermind that doesn't do what you are after

    This should do what you are after

    find /root/dir/with/subfolders -type f -exec rsync -av {} /dest/ --dry-run \;

    remove dry-run when satisfied. This was the cleanest single line option i could figure out, similar to above. I prefer rsync though as it keeps attributes intact. You can use it to delete source files too with the --remove-source-files flag
     
    Last edited: May 20, 2019

Share This Page

Advertisement: