-3

Good day,

I need to move 786 folders to another location, each one of them has at least 1 file inside. Most of those folders do have the same named folders in the location I need them to move, as well as they do have same named files inside them. For example folder 33 has to be moved. Folder hierarchy looks like this: /33/1.TIF. In the location I need this folder to be moved is the same folder with the same named file in it. If I will try to move this folder there, they will conflict with each other. So I need to evade it.
I have a CSV file with old names of folders and new names for them as well. I am new to linux and shell itself, so I really don't know where to start.

Marks Gniteckis
  • 473
  • 1
  • 6
  • 18
  • 1
    Starting here http://stackoverflow.com/questions/4286469/how-to-have-bash-parse-a-csv-file would be a good idea. If you've never done any bash programming, a tutorial might help. – Fang Jul 22 '16 at 12:33
  • First, make a copy of a few source-directores and target directories. Learn some shell commands and how to combine them with the pipe operator. Try to experiment with this small subset of files and folders, so you avoid (1) overwriting important files and/or (2) creating a mess with lots of redundant copies in the target directory. – knb Jul 22 '16 at 14:16
  • 1
    Before we can help, we need to know if you want to *overwrite* the destination files with the same name, or do you want to *preserve* the existing destination file and move the new file into the same location with a suffix such as `/33/1.TIF_001`? – David C. Rankin Jul 23 '16 at 05:13
  • I kep thinking the answer to your question is "mv". Your questions implies what you are trying to do is rename "/a/b/c/THE_DIR" to "/a/b/c/THE_DIR2", which mv will do. If you are trying to move "/a/b/c/THE_DIR" to "/d/e/f/THE_DIR" then assuming "/d/e/f" exist and you have permission, then mv again will work. If you want to move "/a/b/c/THE_DIR" to "/a/b/c/d/THE_DIR", you need to make sure "a/b/c/d" exist. – TenG Jul 24 '16 at 12:34
  • @DavidC.Rankin Let's say I have 2 folders - OLD and NEW. In OLD I have folder named 1 which contains files 1.TIF, 2.TIF. Folder NEW has the same folder with the same files in it. I want files from OLD 1 to be moved into NEW 1 and re-named into 3.TIF, 4.TIF – Marks Gniteckis Jul 24 '16 at 14:13
  • OK, that makes sense and is doable. I'll provide an example which should get you going. I'll have a bit of time later this evening. – David C. Rankin Jul 24 '16 at 20:22

1 Answers1

0

There are a number of ways to go about merging the directories. The difficulty lies in checking if an file with the same name already exists in the target directory and then incrementing the name of the source file to avoid overwriting the target.

Given your naming convention of #.TIF, one way to accomplish this to scan the files in the target directory and determine the max #. You also need to scan the source files as well to account for the case where a source file does not already exist in the target.

One you have the max # for the set of files, you simply loop over each file, checking if it already exists, if so, move the file from its current # to # + max in the target dir. If the file doesn't already exist, just move it. The same applies for a source dir that does not already exist in the target directory structure -- just move it.

Putting all the pieces together, you could do something similar to the following where the script takes as arguments the old directory name, new directory name, and ext (default TIF):

#!/bin/bash

[ -z "$1" -o -z "$2" ] && {     ## validate 2 arguments given
    printf "error: insufficient input, usage: %s old new\n" "${0##*/}"
    exit 1
}

old="$1"    ## assign arguments to 'old' and 'new' (readability)
new="$2"
ext="${3:-TIF}"

[ -d "$old" -a -d "$new" ] || { ## validate both old/new are directories
    printf "error: invalid input.\n"
    [ -d "$old" ] || printf "  '%s' is not a directory.\n" "$old"
    [ -d "$new" ] || printf "  '%s' is not a directory.\n" "$new"
    exit 1
}

while read -r dname; do                 ##  for each old directory
    max=0                               ##  zero max
    nname="${dname/$old/$new}"          ##  generate new dir name 
    if [ -d "$nname" ]; then            ##  check if new dir exists, if so

        ## get max file # in old & new
        for i in "$dname"/*; do         ##  for each file in old
            [ -f "$i" ] || continue     ##  skip if not file
            fn="${i%.$ext}"             ##  get the number
            fn=${fn#${dname}/}
            ((fn > max)) && max=$fn     ##  update max if greater
        done

        for i in "$nname"/*; do         ##  do the same for new dir
            [ -f "$i" ] || continue
            fn="${i%.$ext}"
            fn=${fn#${nname}/}
            ((fn > max)) && max=$fn
        done

        ## move files from old to new
        for i in "$dname"/*; do         ##  for each file in old
            [ -f "$i" ] || continue
            newfn="${i/$old/$new}"      ##  form new file name
            if [ -f "$newfn" ]; then    ##  check if it exists, if so
                fn="${i%.$ext}"
                fn=${fn#${dname}/}      ##  add max to number and mv
                printf "mv %s %s\n" "$i" "${newfn%/*}/$((fn + max)).$ext"
                mv "$i" "${newfn%/*}/$((fn + max)).$ext"
            else                        ##  otherwise, just mv
                printf "mv %s %s\n" "$i" "$newfn"
                mv "$i" "$newfn"
            fi
        done
    else    ## if no new dir exists, move old new
        printf "mv %s %s\n" "$dname" "$nname"
        mv "$dname" "$nname"
    fi
done < <(find "$old" -type d)

For example, if you had the following old and new directory structures:

$ tree old
old
├── 22
│   ├── 1.TIF
│   ├── 2.TIF
│   ├── 3.TIF
│   └── 4.TIF
├── 23
│   ├── 1.TIF
│   ├── 2.TIF
│   ├── 3.TIF
│   ├── 4.TIF
│   └── 5.TIF
└── 24
    ├── 1.TIF
    └── 2.TIF

$ tree new
new
├── 22
│   ├── 1.TIF
│   ├── 2.TIF
│   └── 3.TIF
└── 23
    ├── 1.TIF
    ├── 2.TIF
    └── 3.TIF

The script would produce the following results (you can delete the printf statements, or redirect the output to /dev/null to suppress the text)

$ bash mvoldnew.sh old new
mv old/24 new/24
mv old/22/1.TIF new/22/5.TIF
mv old/22/2.TIF new/22/6.TIF
mv old/22/3.TIF new/22/7.TIF
mv old/22/4.TIF new/22/4.TIF
mv old/23/1.TIF new/23/6.TIF
mv old/23/2.TIF new/23/7.TIF
mv old/23/3.TIF new/23/8.TIF
mv old/23/4.TIF new/23/4.TIF
mv old/23/5.TIF new/23/5.TIF

now the new directory tree contains the following:

$ tree new
new
├── 22
│   ├── 1.TIF
│   ├── 2.TIF
│   ├── 3.TIF
│   ├── 4.TIF
│   ├── 5.TIF
│   ├── 6.TIF
│   └── 7.TIF
├── 23
│   ├── 1.TIF
│   ├── 2.TIF
│   ├── 3.TIF
│   ├── 4.TIF
│   ├── 5.TIF
│   ├── 6.TIF
│   ├── 7.TIF
│   └── 8.TIF
└── 24
    ├── 1.TIF
    └── 2.TIF

Look it over and let me know if you have any questions, or if I misunderstood your clarification.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85