1

I have many directory with different name, each of them contain a subdirectory named httpd-ack (same name for all of them) in which are stored files.

I need a command to recursively enter each directory, enter subdir httpd-ack, move all files one level up and then delete the httpd-ack folder (which is empty now).

start is

name1/httpd-ack/(files)

name2/httpd-ack/(files)

name3/...[...]

ending should be

name1/(files)

name2/(files)

name3....[...]

Any help will be much appreciated....

  • Welcome to Ask Ubuntu! I recommend you [edit] to clarify: (1) Does this have to operate recursively, where http-ack directories may be nested very deeply (e.g. name4/foo/bar/baz/http-ack)? (2) If so, should http-ack directories residing inside other http-ack directories be processed? Based on your examples, I think that this does not need to operate recursively and that you already have a list of all the directories (shown in the question as name1, name2, etc.). But I'm not totally sure and Jos has interpreted the question as requiring recursion so I figured I'd check. – Eliah Kagan May 30 '20 at 15:46
  • Right question. The httpd-ack subdir is nested only one level down, so maxdepth 1 is to be added to find command – Gianluca Garofalo May 31 '20 at 21:02
  • @EliahKagan I believe the duplicate I picked solves the question but it would be great if you could confirm. – WinEunuuchs2Unix Jun 08 '20 at 01:43
  • @WinEunuuchs2Unix Although the question here is described in a way that makes it seem recursive ("recursively enter each directory"), what's actually needed here is nonrecursive. It's something of a judgment call, as to whether this and How to move some files to their parent directory?, and their answers, are similar enough for this to be considered a duplicate. I would not consider this to be a duplicate of that. – Eliah Kagan Jun 25 '20 at 22:56

2 Answers2

2

Thanks to @Jos, this worked for me:

  1. Create a file named movefiles.sh (and set it executable) with the following code:

    #!/bin/bash
    path=$1
    echo "Now processing $path" 
    cd "$path" 
    if [ -d "./httpd-ack" ]; then 
     cd httpd-ack 
            mv * ../ 
            cd .. 
            rmdir httpd-ack 
        fi
    
  2. Invoke find as follows:

    find . -maxdepth 1 -type d -exec ./movefiles.sh {} \;
    

It worked like a charm... (I didn't try @bac0n solution.)

Eliah Kagan
  • 117,780
  • The indenting shown in your script is unusual, and I wondered if maybe that was unintentional, but I kept it as it was just in case. If you're willing for it to be improved, you may want to [edit] this (or, if for some reason you don't want to do that, you could ping me by including @EliahKagan in a comment here and I'll edit it). – Eliah Kagan Jun 07 '20 at 22:24
0

This script should be a good start:

#!/bin/bash

moveFiles () {
    path=$1
    echo "Now processing $path"
    cd "$path"
    if [ -d "./httpd-ack" ]; then
        cd httpd-ack
        mv * ../
        cd ..
        rmdir httpd-ack
    fi
}

find top/level/dir -type d -exec moveFiles {} \;

First, it defines a function moveFiles that moves into the httpd-ack directory (if one is present) and moves all files upwards, then cds up and deletes the now empty httpd-ack.

Then it finds all directories, starting from /top/level/dir, and calls the newly defined function on each of them.

I'm sure this could be improved. Editors, feel free.

Jos
  • 29,224
  • Has this been tested? -exec only runs external commands, and moveFiles is a shell function. When I replace top/level/dir with a valid path and run it, I get find: ‘moveFiles’: No such file or directory (as expected). If this seems to work, all I can think of is maybe you originally wrote moveFiles as a script and put it in a directory in your $PATH? (You encouraged edits, but fixing this would be a major change. Also, I'm not sure how to make this method work properly: it looks like dir/http-ack/http-ack may be skipped, depending on the order in which find enumerates dir.) – Eliah Kagan May 30 '20 at 15:40
  • 1
    as been stated above by @Eliah, the script doesn't execute the function call. I put the code for MoveFiles in a separate script, and called it with:

    find . -maxdepth 1 -type d -exec ./movefiles.sh {} ;

    and it worked!!! TNX!

    – Gianluca Garofalo May 30 '20 at 15:52
  • Please Gianluca, write your solution in an answer, and I'll delete mine. – Jos May 30 '20 at 19:11
  • @EliahKagan No I hadn't tested it. In fact I had forgotten that find uses a new shell for the exec parameter, therefore cannot use the function definition. Gianluca's solution is what is needed. – Jos May 30 '20 at 19:15
  • you need to call your function with bash -c example function f(){ echo helo; }; find -type f -exec bash -c f ; ... find does not start a shell therefor no function are available –  May 30 '20 at 19:39