Say I have folders named user/john/john1
, john2
and john3
and I have one file called dog.txt
inside each of them. I want to create a separate folder called johns_dogs
and copy all the dog.txt
from each folder into this new folder, but with the files renamed as john1_dog.txt
, john2_dog.txt
, john3_dog.txt
.
How would I go about this? I assume I can use a for loop for this, and I have been playing around with it..i just can't seem to get it right; specifically isolating the folder names to apply to the file name using the linux terminal. Using GUI is not an option. Thank you :)
for fname in user/john/*/dog.txt;
do
new_name=basename $(PWD)
cp user/john/*/dog.txt > $new_name.txt;
done
This is what I've tried to do...but it doesn't work, and i don't know why?
CodePudding user response:
One option would be to use bash string substitution via parameter expansion to build the desired output path for each file:
for f in ./user/john/*/dog.txt ; do
new="${f//\//_}"
new="${new/._user_john_/./johns_dogs/}"
cp "$f" "$new"
done
or as one-liner:
for f in ./user/john/*/dog.txt ; do new="${f//\//_}" ; new="${new/._user_john_/./johns_dogs/}" ; cp "$f" "$new"; done
After running above command contents of .johns_dogs
directory:
find ./johns_dogs/*
./johns_dogs/john1_dog.txt
./johns_dogs/john2_dog.txt
./johns_dogs/john3_dog.txt
./johns_dogs/john4_dog.txt
./johns_dogs/john5_dog.txt
String replacement details:
new="${f//\//_}" # replace all '/' with '_' in original path to create new path
new="${new/._user_john_/./johns_dogs/}" # replace '._user_john_' with './johns_dogs' to complete new path
CodePudding user response:
Instead of some utterly incomprehensible, works-by-voodoo-magic, write-test-debug-then-throw-away script, my approach in similar cases is as follows:
- Use the
ls
command to create a "long" listing of your files. (One full filename per line.) - Pipe it into a text file.
- Open the text file in an editor which supports column editing.
- Copy the column of filenames to the clipboard.
- While keeping the copied column in the clipboard:
- Edit the column of filenames, so as to turn them into the destination filenames. (Use column-mode and/or search-and-replace for this.)
- Paste the column of original filenames from the clipboard into the text file, right before the column of altered filenames.
- Prepend
cp
at the start of each line. - Save the text file as a shell script. (Prepend
#!bash
, do the necessarychmod
) - Run the shell script.
It might seem like a lot of work, but actually you can do it very quickly (as long as you do not have to manually modify each line) and the great benefit of it is that you can just examine it with your eyes and have a fairly high degree of confidence that once run, it will do the right thing, whereas the script might destroy your filesystem and you will only know after the fact.
I mean, please do not get me wrong, I am a Software Engineer, I write code for a living, I solve problems by writing code, but there are some cases where it is just not worth writing code.