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.
CodePudding user response:
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:
- Gets the current child folders.
- Creates a new folder called
out
. - Loops over the folder child folders and copies the files to the new folders.
Note: the script should be ran on the parent folder.
CodePudding user response:
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
CodePudding user response:
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
CodePudding user response:
#!/usr/bin/env bash
new_dir="<target_folder>"
find "$HOME/Sources/" -type f -name 'image.fits' | while read -r fileName; do
mkdir -p "$HOME/Sources/$new_dir/"
mv "$fileName" "$HOME/Sources/$new_dir/$((n ))_${fileName##*/}"
done
CodePudding user response:
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/