2

How may I copy multiple files in multiple folders into one folder and change their names according to what directory they are copied from?

Initial directory hierarchy:

folder1/
    file1.gz
    filexyz.gz

folder2/
    file1.gz
    filexyz.gz

folder3/
    file1.gz
    filexyz.gz

Result:

folder1_file1.gz
folder2_file1.gz
folder3_file1.gz
folder1_filexyz.gz
folder2_filexyz.gz
folder3_filexyz.gz
1

4 Answers 4

1

Using a simple shell loop, assuming the files should be copied to the directory given by the value $destdir:

for pathname in */*.gz; do
    cp -i -- "$pathname" "$destdir/$( dirname -- "$pathname" )_$( basename -- "$pathname" )"
done
5
  • Also is it possible to keep the modified files in the same parent folders? Oct 4, 2019 at 22:21
  • @user1703276 Modified files? There is no modification to the files being done here.
    – Kusalananda
    Oct 4, 2019 at 22:26
  • sorry I meant renamed files like all folder1_* in folder1. Oct 4, 2019 at 22:27
  • @user1703276 I'm still not entirely sure I understand. Are you referring to my last sentence in the answer? I'm just having second thought about that particular sentence now and I think it ought to be fine with `$destdir" being any existing directory, even if it's a subdirectory in the current directory.
    – Kusalananda
    Oct 4, 2019 at 22:29
  • yes I was referring to your last comment. Yes, the initial directory should be the destination directory. Thank you. Oct 4, 2019 at 22:35
1

With prename/rename (aka Larry Wall's Perl-rename)(rename on Debian/Ubuntu, prename on RHEL/CentOS, IIRC):

In the parent of folder1, folder2, folder3:

rename -n s:/:_: */*

-n is the "dry run" parameter, replace by "-v" or remove if the renaming looks good.

Basically this move files from directory/file to directory_file in the current directory. If you have several folder levels and are using bash, you can use

shopt -s globstar   # Possibly already set, necessary for the "**"
rename -n s:/:_:g **/*

And this moves files from some/path/to/file to some_path_to_file in the current directory.

1
0

Something like this?

#!/bin/bash -ex
DESTDIR="PATH/TO/FINAL/DESTINATION/DIRECTORY"
for DIRS in /PATH/TO/YOUR/DIRECTORIES/*/;
do
    for FLES in $DIRS*.gz;
    do
        cp $FLES $DESTDIR/$(echo $(basename $DIRS)"_"$(basename $FLES))
    done
done

Edit: I've bothered to add no explanations to the code because the OP hasn't bothered to show that they've attempted to solve the problem themselves (if at all). But assistance should be rendered all the same, hence my post.

1
  • Note that $( echo $( ... ) ) is an anti-pattern that could be replaced by $( ... ) (unless you want the result of $( ... ) to undergo the special processing of backslashes that some implementations of echo performs).
    – Kusalananda
    Oct 1, 2019 at 7:57
0

Try this,

  find folder[1-3] -type f -name '*.gz' | while read -r FILE; do cp "$FILE" "${FILE//\//_}"; done
  • folder[1-3] source location.
  • -type f search only for files.
  • -name '*.gz' filename suffix with .gz.
  • ${FILE//\//_} replace '/' with underscore.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .