Shell script to get name of file, delete original file, rename blank file
Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Shell script to get name of file, delete original file, rename blank file
Hi,
I've had a request to help out someone accomplish a task involving a load of files in a directory.
Essentially, what I need to achieve is along the lines of the following, for each file in the directory:
- Get the file name & assign to var
- delete the original file
- take a copy of a placeholder file (which we will just call placeholder.txt)and add .tmp extension
- rename the copy of the placeholder.txt.tmp file to the original file name based on the var
I have a few ideas but I am not sure where best to start and I am tripping up with my script so far - any pointers would be greatly appreciated
Overwriting would also be an option so long as the file name stays the same - say for instance we have files 1.txt 2.txt ...... 10.txt
I need to loop through the directory, get each file name, and basically replace the file with that name with a placeholder file with the same name
It's a bit of an unusual request though admittedly
I have been trying to do some basic scripting but I am tripping up with the logic needed
I suppose another way would be to go through the directory, get all the file names (assign to array?), and then for each file do a cp placeholder.txt filename.txt, and then as you say...set it to overwrite the original
I would need to get the filename without the extension though, otherwise it would end up being file.txt.txt i guess..
Thanks for that article, I must admit I did not know that, and I will indeed follow your suggestion
However I am very close with the other way and I just want to fix it to understand where I am going wrong at the last hurdle:
I now have:
Code:
for i in $(ls | grep txt); do \cp ../placeholder.txt "$i"; done
And this works just fine, when I open a a TXT with the original file name, I can see that the new placeholder content is now there. EXCEPT for TXT files with spaces in the file names...and I then just see several files. For example. TXT WITH SPACES.TXT ends up looking like this in an ls:
TXT
SPACES.TXT
WITH
and also the original TXT WITH SPACES.txt
I have tried '$i' and "$i" - alas, no difference (though it does throw errors with just 'i', "i" works but the result is the same as above)
Safer to quote the $i in case its value contains something bash will substitute:
Code:
for i in *.txt; do cp placeholder.txt "$i"; done
Ah ha! That's got it, even with the spaces. Oddly I was tring for i in *.txt earlier today and I was getting errors that suggested it was looking inside the files, but I was obviously doing something wrong.
I am still curious to know then why when I use "$i" in the other command it doesn't work.
But thanks for the assistance, this has been way simpler than I first thought..and I learned something. Win, win!
Thanks for that article, I must admit I did not know that, and I will indeed follow your suggestion
However I am very close with the other way and I just want to fix it to understand where I am going wrong at the last hurdle:
I now have:
Code:
for i in $(ls | grep txt); do \cp ../placeholder.txt "$i"; done
And this works just fine, when I open a a TXT with the original file name, I can see that the new placeholder content is now there. EXCEPT for TXT files with spaces in the file names...and I then just see several files. For example. TXT WITH SPACES.TXT ends up looking like this in an ls:
TXT
SPACES.TXT
WITH
and also the original TXT WITH SPACES.txt
I have tried '$i' and "$i" - alas, no difference (though it does throw errors with just 'i', "i" works but the result is the same as above)
It's because the for is splitting on spaces, your problem is the for i in $(ls | grep txt). If you had three files: a.txt, b.txt, and "c d.txt" (with a space), your "ls | grep txt" would spit out the single string "a.txt b.txt c d.txt". The for would then split on spaces, giving you "a.txt", "b.txt", "c", and "d.txt". This is why you want to do the for over *.txt directly, without throwing an intermediate ls in the middle. When you do "for i in *.txt" it will handle the spaces correctly. "for i in $(ls *.txt)" will not.
But apparently didn't make any difference...so, what am I missing?
It is the same issue. FILES is set to the output of find including whitespace. If you then use $FILES unquoted, bash turns it into a list of whitespace-separated words separated by spaces.
The classic robust idiom for looping over file names is:
Code:
while IFS= read -r -d '' file
do
Do something with "$file"
done < <(find <whatever> -print0)
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.