I am using Cygwin as Linux shell, I have following contents in my current working directory:

Files :




Now I want to copy files as below:

Abc.dat -> W_Abc_w 
123.dat -> W_123_w 
456.dat -> W_456_w

How to achieve this in a single line linux command? I need a generic solution which can be used for similar cases in future...

Destination directory always exists, but number of characters in file name will vary. Destination directory name will always contain the file name of file to be copied along with other extra characters. Destination directory names have unique pattern eg. Abc_sa_file_name_1 second directory name will be Abc_sa_file_name_2. File names also has pattern e.g kim_1. Kim_2 .
I will be moving or copying file kim_1 to Abc_sa_kim_1_1. I wish to operate complete pattern in one command.

  • In a single command you mean without for loop? Nov 20, 2019 at 18:15
  • Right, may be using system variables Nov 20, 2019 at 18:18
  • That one very specific result, or by following some pattern (that you should describe)?
    – Jeff Schaller
    Nov 20, 2019 at 18:27
  • Using the patterns and variables. Nov 20, 2019 at 18:32
  • Do your filenames always match ???.dat? Will the destination directories always exist?
    – Jeff Schaller
    Nov 20, 2019 at 18:38

1 Answer 1


In one command (line):

cp Abc.dat W_Abc_w/; cp 123.dat W_123_w/; cp 456.dat W_456_w/

The trailing slashes are not required, but a habit to indicate that the intention is to put the file into a destination directory not as a new file.

As a generic loop with a pattern:

for f in ???.dat
  [ -d W_"${f%.dat}"_w ] && cp -- "$f" W_"${f%.dat}"_w

This picks up every filename that has three characters followed by .dat and copies them into the correspondingly-named directory, if that directory already exists. The filename expansion inside the cp command strips off the trailing .dat.

If you were interested in a command-line approach that does not use a loop -- but also moves the files instead of copies them -- you could use zsh:

autoload zmv
zmv '(???).dat' 'W_$1_w'
  • Last one seems good, I will try it and let you know what happened! Thanks Nov 20, 2019 at 18:44
  • @VikramTidake I believe that mmv is available for Cygwin, providing shell-independent functionality similar to zmv if you prefer ex. mmv '???.dat' 'W_#1#2#3_w/' - it has a -c option (and possibly a mcp binary) to copy rather than move. Nov 20, 2019 at 20:00
  • How one can perform this operation with <find> command? Nov 29, 2019 at 14:32
  • Vikram, if your requirement is to use "find", please make that explicit in your question. I will re-add the "find" tag. Thank you.
    – Jeff Schaller
    Nov 30, 2019 at 14:15

You must log in to answer this question.

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