1

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

Files :

Abc.dat 
123.dat 
456.dat

Directories:

W_Abc_w 
W_123_w 
W_456_w

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? – schrodigerscatcuriosity Nov 20 '19 at 18:15
  • Right, may be using system variables – Vikram Tidake Nov 20 '19 at 18:18
  • That one very specific result, or by following some pattern (that you should describe)? – Jeff Schaller Nov 20 '19 at 18:27
  • Using the patterns and variables. – Vikram Tidake Nov 20 '19 at 18:32
  • Do your filenames always match ???.dat? Will the destination directories always exist? – Jeff Schaller Nov 20 '19 at 18:38
3

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
do
  [ -d W_"${f%.dat}"_w ] && cp -- "$f" W_"${f%.dat}"_w
done

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'
| improve this answer | |
  • Last one seems good, I will try it and let you know what happened! Thanks – Vikram Tidake Nov 20 '19 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. – steeldriver Nov 20 '19 at 20:00
  • How one can perform this operation with <find> command? – Vikram Tidake Nov 29 '19 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 '19 at 14:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.