0

I have this structure of folders:

/Folder1/Folder2/output/0653/3547/0112945601/ 
/Folder1/Folder2/output/0653/3547/0112945602/

only the 5th subfolder changes.

I want to list all of the 5th subfolders and reorganize them like this:

/Folder1/Folder2/output01/0653/3547/0112945601/
/Folder1/Folder2/output02/0653/3547/0112945602/ 
/Folder1/Folder2/output03/0653/3547/0112945603/ 
...
/Folder1/Folder2/output<nn>/0653/3547/01129456<nn>/ 

and if we have 10 subfolders, I need to have 10 output folders, following this logic.

I tried using

find -maxdepth 5 -type d 

and put it inside a while loop but I can't work only with the 5th subfolder.

What do you think I can do?

Freddy
  • 25,172
  • 1
  • 21
  • 60

3 Answers3

1
for dir in Folder1/Folder2/output/*/*/*; do
    suffix=${dir:(-2)}
    subdir="$(cut -d '/' -f 4- <<<$dir)"
    newdir="Folder1/Folder2/output${suffix}/${subdir}"
    echo mkdir -p "$newdir"
    echo mv "$dir"/* "$newdir"/
done

After you've dry-runned this, if it looks like it's generating the commands that will work for you, then remove the echo statements to actually move the files.

spuck
  • 306
  • 1
  • 5
1

Assuming you're currently located in the directory where Folder1 is located:

#!/bin/bash

# Don't even attempt to do something
# if we're in the wrong place.
cd Folder1/Folder2 || exit 1

# Make the shell remove patterns that aren't matched,
# rather than leaving them as they are.
shopt -s nullglob

for dirpath in output/*/*/*/; do
        if [[ $dirpath =~ output/(.*)/[^/]*(..)/ ]]; then
                # "${BASH_REMATCH[1]}" is something like "0653/3457"
                # "${BASH_REMATCH[2]}" is the 2-character suffix, like "01"

                newdir=output${BASH_REMATCH[2]}/${BASH_REMATCH[1]}
                mkdir -p "$newdir" &&
                mv "$dirpath" "$newdir"
        fi
done

This uses the regular expression matching feature of bash to pick out the numerical suffix from the end of the directory pathname and constructs a new output directory name using this.

This would take the directory structure

.
`-- Folder1/
    `-- Folder2/
        `-- output/
            `-- 0653/
                `-- 3547/
                    |-- 0112945601/
                    `-- 0112945602/

and turn it into

.
`-- Folder1/
    `-- Folder2/
        |-- output/
        |   `-- 0653/
        |       `-- 3547/
        |-- output01/
        |   `-- 0653/
        |       `-- 3547/
        |           `-- 0112945601/
        `-- output02/
            `-- 0653/
                `-- 3547/
                    `-- 0112945602/

Empty directories in Folder1/Folder2/output could then be removed using

find Folder1/Folder2/output -type d -empty -delete

or, using standard find and ignoring errors from rmdir when it tries to remove a non-empty directory,

find Folder1/Folder2/output -depth -type d -exec rmdir {} \; 2>/dev/null

which leaves

.
`-- Folder1/
    `-- Folder2/
        |-- output01/
        |   `-- 0653/
        |       `-- 3547/
        |           `-- 0112945601/
        `-- output02/
            `-- 0653/
                `-- 3547/
                    `-- 0112945602/

You would obviously run this on a copy of your data first.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
-1
#!/usr/bin/env bash
PATH="/folder1/folder2/folder3"
HIERARQUIA=$(/usr/bin/find $PATH/????/????/  -maxdepth 0 -type d | /usr/bin/cut -d "/" -f5-|/usr/bin/sort -s )
OUTPUT=1

for i in $HIERARQUIA
    do
        SUBPASTAS=$(/usr/bin/find $PATH/$i -maxdepth 1 -type d | /usr/bin/cut -d "/" -f7 |/usr/bin/sort -s)
        for a in $SUBPASTAS
            do
                /usr/bin/mkdir -p $PATH/output$OUTPUT/$i$a
                /usr/bin/mv $PATH/$i$a/* $PATH/output$OUTPUT/$i$a
                OUTPUT=$(($OUTPUT +1))              
            done
            OUTPUT=1
    done

I found that result, and it achieved the goal. for everyone who one day has a similar problem here is the code.

Thanks to everyone who responded and tried to help me

  • If you didn't use `PATH` as a variable, then you would not need to use the absolute paths to the utilities that you use. The `PATH` variable should be a `:`-delimited string of the directory paths where executables may be found. – Kusalananda Feb 11 '21 at 20:20
  • Also note that in your question you say `/Folder1/Folder2/output`, but it seems that you use `/folder1/folder2/folder3` in your answer. Your use of `find` is not needed at all and it's unclear why you sort the output before looping over it (see [this question](https://unix.stackexchange.com/questions/321697)). This would break if any directory path contained a whitespace character, or a filename globbing character (see also [this question](https://unix.stackexchange.com/questions/131766), [and here](https://unix.stackexchange.com/questions/68694)). – Kusalananda Feb 11 '21 at 20:23
  • @ Kusalananda I use sort because my folders are number ordened ... example: $PATH/????/????/?????? is $PATH/0001/0001/000001 $PATH/0001/0001/000002 $PATH/0001/0001/000003 and I want to work with this in order. Tnks for the tips. tnks everyone. – Samuel Santiago Feb 12 '21 at 14:02