Recursively copy (and rename) files to their own same directory with another name

Dario Fumagalli

This Q and A will cover a very specific yet common case: given many files with the same or similar name each in its own directory, create a copy of each of them in their original directory but with another name.

You might wonder which rare case would require such operation. It's not so rare. Some emerging software, expecially those based on the MVC (Model / View / Controller) design pattern may require the programmer to implement the various components each in a different directory.

Example:

software root
|
|-- Model => MyCustomComponent.php
|
|-- View => MyCustomComponent.php
|
|-- Controller => MyCustomComponent.php
|
\-- Translations
         |
         |-- English => MyCustomComponent.php
         |
         |-- French => MyCustomComponent.php
         |
         |-- Italian => MyCustomComponent.php
         |
         |-- Spanish => MyCustomComponent.php
         |

An example of a quite famous software implementing such structure would be the popular e-commerce application OpenCart. But there are many others.

A common practice is to create new components by copying an existing one or a core one, apply variations and save them. In case inheritance and similar can't help us, we end up having to duplicate 10-20 files. An utterly boring and error prone process.

This is a typical example: from a bank transfer script implement a direct debit script by using the former as "boilerplate code" (don't bash me, I did not create this architecture). Between translations, Model, View and Controller management and others, the number of files to copy each in its deep directory quickly becomes cumbersome.

Lots of same name files, one per directory

Dario Fumagalli

This little script comes to help exactly in this situation.

Given a starting directory, a file name pattern, an original file name portion to change and the destination file name portion to use, it will:

  • Deep copy all the matching files preserving attributes over new ones (copy)

or

  • Deep rename all the matching files to the new names (rename)

or

  • Just show a preview list of the potentially affected files (preview).

The last option is expecially useful because selecting the right match that covers a mass of files with names variations or extensions variations may quicky become a challenge. Avoid getting a complete mess by previewing the changes before applying them!

The script is very simple and has NO pretense about being the best, the quickest, the cleanest, the safest. It's what works for me and I have decided to share it in hope somebody else will take benefit.

If you start it with no parameters or a wrong command, it will show some brief instructions:

./copy_multi_files.sh

Usage:
./copy_multi_files.sh command path name_pattern src dest
If command is 'copy' then the script copies src to dest
If command is 'rename' then the script renames src to dest
If command is 'preview' then the script just shows the matched files
Inside path, for every file name matching name_pattern, it copies every src file to dest file


Parameters:

  • Command: it may be one of copy, rename or preview. Copy performs the recursive deep copy onto new files, rename just mass renames existing files, preview just shows which files will be affected and how.

  • Path: it's the starting directory. I suggest doing experiments on small directories to get confidence with the script before trying on your 4 peta-trillion entries file system.

  • Name_pattern: this decides which files shall be affected, so it's important to pick a sensible value. In example, if I wanted to select a lot of scripts whose name starts with "sendmail" I could specify s* for this parameter. For those who know about shell commands, this pattern is internally passed to find.

  • src: this is the portion, a template of file name to replace with dest when forming the copied files names.

  • dest: this is what replaces src in the new copied files names.

A bit of sanity check is performed so that name_pattern and src produce consistent results. That is, only files that match name_pattern and also contain src are selected.

Confusing? Don't worry, I have prepared some examples and "gotchas".


Simple, one folder example:

We have some files in a sub-directory called: apps/res/

We want to copy all the files whose name contains the word: sendmail into new files that in place of sendmail have newthing.

Here is a partial list of apps/res/ contents:

robot.php
sendmail_test.php
sendmail_test2.php
sendmail_test3.php
showinfo.php
show_server_vars.php
version.php

We may issue the following command:

./copy_multi_files.sh preview apps/res/ s* sendmail newthing

This command line tells us that we just want a preview; the starting directory is apps/res/ (that is, it's under our current directory), that we are going to search for all files beginning with s (s*). Among the found files, we are going to pick only those whose name contains sendmail and copy them to files residing in the same directories but with sendmail replaced by newthing.

Here is the output of this preview:

apps/res/sendmail_test.php => apps/res/newthing_test.php
apps/res/sendmail_test2.php => apps/res/newthing_test2.php
apps/res/sendmail_test3.php => apps/res/newthing_test3.php

You see, even if we specified s* as search pattern, the script was "smart" enough to just pick the subset of "beginning by s" files that also contains "sendmail".

Let's run the command:

./copy_multi_files.sh copy apps/res/ s* sendmail newthing

ls apps/res/ will show how now we have both the original files but also the same files with newthing. If we used "rename" in the line above, we'd only have the newthing files.

newthing_test.php
newthing_test2.php
newthing_test3.php
robot.php
sendmail_test.php
sendmail_test2.php
sendmail_test3.php
showinfo.php
show_server_vars.php
version.php

Let's change the files again. This time we rename them:

./copy_multi_files.sh rename apps/res/ new* new even_newer_

Notice the values used for the various parameters. The directory now is the following:

even_newer_thing_test.php
even_newer_thing_test2.php
even_newer_thing_test3.php
robot.php
sendmail_test.php
sendmail_test2.php
sendmail_test3.php
showinfo.php
show_server_vars.php
version.php


More complex example: let's move to OpenCart's top install folder and return to the the bank transfer MVC files. We need to create copies of those files, each in its respective directory. They will be used to implement a direct debit payment module. Here's the command line and an extract of the output:

./copy_multi_files.sh preview . ban* bank_transfer.* direct_debit

./catalog/view/language/russian/payment/bank_transfer.php => ./catalog/view/language/russian/payment/direct_debit
./catalog/view/language/czech/payment/bank_transfer.php => ./catalog/view/language/czech/payment/direct_debit
./catalog/view/theme/default/template/payment/bank_transfer.tpl => ./catalog/view/theme/default/template/payment/direct_debit


Oops! Something went wrong! Lucky us, for having used the preview. What's wrong in the above command? The "src" argument is the wrong one. In fact, bank_transfer.* is internally passed to a direct "search and replace" function (sed). It's not expanded with a "file globbing" function but as regular expression. Therefore all the files in the preview are transformed into: direct_debit.


Now that we know about this gotcha, we can rewrite the command line to achieve the desired result:

/var/www/copy_multi_files.sh preview . ban* bank_transfer direct_debit

./catalog/view/language/russian/payment/bank_transfer.php => ./catalog/view/language/russian/payment/direct_debit.php
./catalog/view/language/czech/payment/bank_transfer.php => ./catalog/view/language/czech/payment/direct_debit.php
./catalog/view/theme/default/template/payment/bank_transfer.tpl => ./catalog/view/theme/default/template/payment/direct_debit.tpl

Now it works! Now extensions are preserved, even when they change (.php and .tpl).

Follows the little script source code. I strongly suggest to save backups before doing "live" renames and to always use the preview functionality. Remember, this is a recursive Unix script, its effects may be extremely nasty and irreversible!

Source code:

#!/bin/sh

if [ "$#" -eq 0 ] || ( [ "$1" != "preview" ] && [ "$1" != "copy" ] && [ "$1" != "rename" ] )
        then
        echo "Usage:"
        echo "$0 command path name_pattern src dest"
        echo "If command is 'copy' then the script copies src to dest"
        echo "If command is 'rename' then the script renames src to dest"
        echo "If command is 'preview' then the script just shows the matched files"
        echo "Inside path, for every file name matching name_pattern, it copies every src file to dest file"
        echo
        exit 1
fi

for f in $(find "$2" -type f -name "$3" -name "*$4*" )
do
        z=`echo "$f" | sed s/"$4"/"$5"/`

        case "$1" in
                "preview") echo "$f => $z"
                ;;
                "copy") cp -p "$f" "$z"
                ;;
                "rename") mv "$f" "$z"
                ;;
        esac
done

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Recursively copy (and rename) files to their own same directory with another name

From Dev

Copy files to same directory with another name

From Dev

Recursively copy files from one directory to another

From Dev

Recursively copy files from one directory to another

From Dev

Copy and rename files recursively using part of folder name for new name

From Dev

Powershell: find files based on directory name, copy and rename into same folder and keep original

From Dev

How to copy multiple files with a same name from children directory to another directory without losing the parent directory?

From Dev

Copy files of same name into same directory

From Dev

Recursively copy a set of files from one directory to another in PowerShell

From Dev

Search a directory recursively for files listed in a csv, and copy them to another location

From Dev

recursively copy all files from one directory to another with exceptions

From Dev

Python copy files to a new directory and rename if file name already exists

From Dev

How to copy all files with the same name into another directory using cp command

From Dev

rename files based on the directory name

From Dev

Copy files in a directory to another directory

From Dev

Copy files in a directory to another directory

From Dev

Find files in all directories by name in and copy to another directory using rsync

From Dev

Copy files from directory recursively smallest first

From Dev

Find, copy, rename within the same directory

From Dev

Find, rename and copy files to a new directory

From Dev

Powershell recursively copy and change name of files

From Dev

Rename files in subdirectory with the same name as the name of the folder

From Dev

rename folder/directory recursively

From Dev

PHP: rename all files to lower case in a directory recursively

From Dev

How do I batch copy and rename files with same name in different path?

From Dev

find modified files recursively and copy with directory preserving directory structure

From Dev

How to recursively copy files as hard links into directory preserving directory hierarchy?

From Dev

How to rename files with the name of their parent directory?

From Dev

How to rename multiple files in a directory at the same time

Related Related

  1. 1

    Recursively copy (and rename) files to their own same directory with another name

  2. 2

    Copy files to same directory with another name

  3. 3

    Recursively copy files from one directory to another

  4. 4

    Recursively copy files from one directory to another

  5. 5

    Copy and rename files recursively using part of folder name for new name

  6. 6

    Powershell: find files based on directory name, copy and rename into same folder and keep original

  7. 7

    How to copy multiple files with a same name from children directory to another directory without losing the parent directory?

  8. 8

    Copy files of same name into same directory

  9. 9

    Recursively copy a set of files from one directory to another in PowerShell

  10. 10

    Search a directory recursively for files listed in a csv, and copy them to another location

  11. 11

    recursively copy all files from one directory to another with exceptions

  12. 12

    Python copy files to a new directory and rename if file name already exists

  13. 13

    How to copy all files with the same name into another directory using cp command

  14. 14

    rename files based on the directory name

  15. 15

    Copy files in a directory to another directory

  16. 16

    Copy files in a directory to another directory

  17. 17

    Find files in all directories by name in and copy to another directory using rsync

  18. 18

    Copy files from directory recursively smallest first

  19. 19

    Find, copy, rename within the same directory

  20. 20

    Find, rename and copy files to a new directory

  21. 21

    Powershell recursively copy and change name of files

  22. 22

    Rename files in subdirectory with the same name as the name of the folder

  23. 23

    rename folder/directory recursively

  24. 24

    PHP: rename all files to lower case in a directory recursively

  25. 25

    How do I batch copy and rename files with same name in different path?

  26. 26

    find modified files recursively and copy with directory preserving directory structure

  27. 27

    How to recursively copy files as hard links into directory preserving directory hierarchy?

  28. 28

    How to rename files with the name of their parent directory?

  29. 29

    How to rename multiple files in a directory at the same time

HotTag

Archive