Eli
Eli

Reputation: 37

Copying files of the same name from multiple directories into one directory

I am trying to copy multiple files of the same name from different directories into one and have them not overwrite each other by adding some number before the name. I have a file structure like this, where the image.fits files are different files, but have the same name because they are automatically generated and the parent folder name is also auto generated:

~/Sources/<unknown>/<foldername1>/image.fits
~/Sources/<unknown>/<foldername2>/image.fits
~/Sources/<unknown>/<foldername3>/image.fits
...

Is there a way to copy these files into one folder like this:

~/Sources/<target_folder>/1_image.fits
~/Sources/<target_folder>/2_image.fits
~/Sources/<target_folder>/3_image.fits

Like mentioned above the folder names are also automatically generated, so I want to use some kind of wildcard (*) to access them if possible. The command can either be some command, a shell script or python code, whatever works.

EDIT: The final solution I used is based on the one from @Kasper and looks like this:

import os
import shutil

if __name__ == '__main__':
    os.system('mkdir ~/Sources/out')
    child_dirs = next(os.walk('~/Sources/'))[1]
    num=1
    for dir in child_dirs:
        child_child_dirs = next(os.walk('~/Sources/{}'.format(dir)))[1]
        for ch_dir in child_child_dirs:
            if exists('~/Sources/{}/{}'.format(dir, ch_dir))==True:
                shutil.move('~/Sources/{}/{}'.format(dir, ch_dir), '~/Sources/out/{}_image.fits'.format(num))
                num+=1
            else:
                continue

Upvotes: 2

Views: 1774

Answers (5)

sseLtaH
sseLtaH

Reputation: 11227

#!/usr/bin/env bash

new_dir="<target_folder>"
mkdir -p "$HOME/Sources/$new_dir/"
find "$HOME/Sources/" -type f -name 'image.fits' | while read -r fileName; do
    mv "$fileName" "$HOME/Sources/$new_dir/$((n++))_${fileName##*/}"
done

Upvotes: 0

Lime
Lime

Reputation: 372

TARGET_FOLDER_NAME="<target_folder>"
TARGET_FILE_NAME="image.fits"

mkdir -p ~/Sources/$TARGET_FOLDER_NAME/

COUNT=1
find ~/Sources/ -type f -name $TARGET_FILE_NAME | while IFS= read -r -d '' file;
do
    mv $file ~/Sources/$TARGET_FOLDER_NAME/$COUNT_$TARGET_FILE_NAME
    COUNT=$((COUNT+1))
done

Upvotes: 1

M. Nejat Aydin
M. Nejat Aydin

Reputation: 10123

This two-line solution, which doesn't require any programming, is not exactly what you want, but should be close enough, assuming you have cp from GNU coreutils, which is highly probable since the question is tagged with ubuntu-18.04.

shopt -s globstar
cp --backup=numbered Sources/**/image.fits target_folder/

Upvotes: 0

Shakiba Moshiri
Shakiba Moshiri

Reputation: 23794

It is supper easy

first

save your file in an array

mapfile -t files < <(find a b c d e -type f -name \*.txt)

Second

# dry-run
COUNTER=0
for file in ${files[*]}; do ((++COUNTER)); echo  $file dist/${COUNTER}-${file##*/}; done

output:

a/file.txt dist/1-file.txt
b/file.txt dist/2-file.txt
c/file.txt dist/3-file.txt
d/file.txt dist/4-file.txt
e/file.txt dist/5-file.txt

thrid

# safe run
# cp not mv
COUNTER=0
for file in ${files[*]}; do ((++COUNTER)); cp $file dist/${COUNTER}-${file##*/}; done

last

Delete your files after checking your destination directory


Or one line:

COUNTER=0; for file in {a,b,c,d,e}/*; do ((++COUNTER)); echo $file dist/${COUNTER}-${file##*/}; done

Replace echo with cp or mv

Upvotes: 0

Kasper
Kasper

Reputation: 622

This should do the magic:

import os
import shutil

if __name__ == '__main__':
    child_dirs = next(os.walk('.'))[1]
    os.mkdir('out')
    num = 1
    for dir in child_dirs:
        shutil.copy2('{}/image.fits'.format(dir), 'out/{}_image.fits'.format(num))
        num+=1

It does the following:

  1. Gets the current child folders.
  2. Creates a new folder called out.
  3. Loops over the folder child folders and copies the files to the new folders.

Note: the script should be ran on the parent folder.

Upvotes: 2

Related Questions