Batch file to edit multiple .txt files - batch-file

I have over 1300 .txt files where I need to edit the first line of text, replacing one name for another. Can someone please advise of the best way to achieve this?
Any advice would be appreciated.
Thanks
Stu

If this is Linux, then sed is the answer.

Use sed. Here's a simple one-liner that would do what you want:
sed -i '1s/oldtext/newtext/' *.txt
The -i tells sed to edit the files in-place. The 1 at the beginning of the pattern applies it only to the first line. The s// constrution replaces the text.

perl -npi~ -e "s/old/new/g" file.txt
If you're on a Windows machine, install Strawberry Perl.

Related

sed: how to replace sth. by a backslash followed by reference

Despite all the sed-backslash discussions on Stackoverflow I cannot find a working solution for my specific problem. I want to precede a certain string in a file by a backslash: something -> \something.
sed -i -- 's/\(something\)/\\\1/g' file
This always returns the string \1 instead of \something, because for some reason sed thinks it should escape the third backslash. The (from my point of view more logical) behaviour can be achieved by inserting a space between \\ and \1 in the sed command, but then the result is \ something (i.e. with an inserted space in the result) which is not what I want.
I am running this command in a batch file on Windows, using sed from cygwin (I hope this does not matter as I am aiming for a cross-platform solution).
EDIT: /usr/bin/sed version 4.2.2.
In Windows cmd with Cygwin, use this sed command:
sed -e 's/\(something\)/\\\\\1/g' file
You can start your script from a batch file
myBatch.bat
#echo off
c:\cygwin64\bin\bash ./mySed
mySed
#!/bin/bash
echo asdfsomethingasdf | sed 's/\(something\)/\\\1/g'
It can be necessary to use /usr/bin/sed when your path isn't completely set

sed addressing for each of multiple input files

I would like to print from line 10 until the end of the file for each of several files in a folder. For a single file, I would do this with sed -n '10,$p', however when providing multiple input files to sed the addressing becomes in terms of the concatenated files. How can I print using the sed command and address each file's line numbers? This website says that the $ addressing character refers to each file's end if the -s option is used, but this does not work for me on my Macbook Pro.
Ideally I would like the whole procedure to be done with a single tool without writing a loop. I'm ok with the output being concatenated. I'm open to other tools than sed. tail might work for this like so tail -n +10 filenames but this is very very slow, so I imagine sed is better to use.
awk 'FNR>9{print $0}' file1 file2
This will do it

How do I let sed 'w' command know where the filename ends?

Every example I was able to find demonstrating the w command of sed has it in the end of the script. What if I can't do that?
An example will probably demonstrate the problem better:
$ echo '123' | sed 'w tempfile; s/[0-9]/\./g'
sed: couldn't open file tempfile; s/[0-9]/\./g: No such file or directory
(How) can I change the above so that sed knows where the filename ends?
P.S. I'm aware that I can do
$ echo '123' | sed 'w tempfile
> s/[0-9]/\./g'
...
Are there prettier options?
P.P.S. People tend to suggest to split it in two scripts. The question is then: is it safe? What if I was going to branch somewhere after the w command, and so on. Can someone confirm that any script can be split in two after any command and that will not affect the results?
Final edit: I checked that multiple -e work just as concatenated commands. I thought it was more complex (like the first one should always exit before the second one starts, etc.). However, I tried splitting a {..} block of commands between two scripts and it still worked, so the w thing is really not a serious problem. Thanks to all.
You can give a two line script to sed in one shell line:
echo '123' | sed -e 'w tempfile' -e 's/[0-9]/\./g'
This might work for you (if you're using BASH and probably GNU sed):
echo '123' | sed 'w tempfile'$'\n'';s/[0-9]/\./g'
Explanation:
The r, R and w commands need a newline to terminate the file name.
The answer to the question is "newline":
sed will treat a non-escaped literal newline as the end of the file name.
If your shell is bash, or supports the $'\n' syntax, you can solve the OP's original question this way:
echo '123' | sed 'w tempfile'$'\n''s/[0-9]/\./g'
In a more limited sh you can say
$ echo '123' | sed 'w tempfile'\
> 's/[0-9]/\./g'
What I did here was write \ as an escape, then hit enter and wrote the rest of the command there. Note that here I am escaping the newline from bash but it is being passed to sed.
Reverse the 2 sed command sequences like this:
echo '123' | sed 's/[0-9]/\./g;w tempfile'
i.e. perform replacements first and then write pattern space into a file.
EDIT: There was some misunderstanding whether OP wants replaced text in final file or not. My above command puts replaced text in tempfile. Since this is not what OP wanted here is one more version that avoids it:
echo '123' | sed -e 'h;s/[0-9]/\./g;g;w tempfile'

Batch File using sed in windows - unexpected append instead of replace

I've been tasked with migrating a group of batch scripts to Windows 7 (from XP) and have had a few problems using sed for substitution. What i need the line to do is find LogPath and anything inside the double quotes should be replaced with ABC (just for testing - will actually be a UNC path).
However instead I'm getting two strange problems:
it's deleting the first double quote
more importantly it isn't
actually replacing anything inside the quotes, but instead is just
appending to this string
Here is the relevant line of the script:
sed \\fs-bri-01\9732\9732.hfls -i -e s,LogPath="*.",LogPath="ABC",g
This script works on Windows XP but not Windows 7.
Maybe the problem comes from the UNC path:
pushd \\fs-bri-01\9732
sed 9732.fls -i -e s,LogPath="*.",LogPath="ABC",g
popd
But maybe the problem comes from the quote characters and the way sed gets its argv array. Then you can try:
sed -i -e "s/LogPath=\".*\"/LogPath=\"ABC\"/g" \\fs-bri-01\9732\9732.hfls
Well figured a work around posting it below for anyone stuck in the same situation.
sed \\fs-bri-01\9732\9732.hfls -i -e "s/LogPath=\"[\:A-Z0-9a-z_\\\/\.\ ]*\"/LogPath=\"ABC\"/g"

<0xEF,0xBB,0xBF> character showing up in files. How to remove them?

I am doing compressing of JavaScript files and the compressor is complaining that my files have  character in them.
How can I search for these characters and remove them?
You can easily remove them using vim, here are the steps:
1) In your terminal, open the file using vim:
vim file_name
2) Remove all BOM characters:
:set nobomb
3) Save the file:
:wq
Another method to remove those characters - using Vim:
vim -b fileName
Now those "hidden" characters are visible (<feff>) and can be removed.
Thanks for the previous answers, here's a sed(1) variant just in case:
sed '1s/^\xEF\xBB\xBF//'
On Unix/Linux:
sed 's/\xEF\xBB\xBF//' < inputfile > outputfile
On MacOSX
sed $'s/\xEF\xBB\xBF//' < inputfile > outputfile
Notice the $ after sed for mac.
On Windows
There is Super Sed an enhanced version of sed. For Windows this is a standalone .exe, intended for running from the command line.
perl -pi~ -CSD -e 's/^\x{fffe}//' file1.js path/to/file2.js
I would assume the tool will break if you have other utf-8 in your files, but if not, perhaps this workaround can help you. (Untested ...)
Edit: added the -CSD option, as per tchrist's comment.
Using tail might be easier:
tail --bytes=+4 filename > new_filename
#tripleee's solution didn't work for me. But changing the file encoding to ASCII and again to UTF-8 did the trick :-)
I've used vimgrep for this
:vim "[\uFEFF]" *
also normal vim search command
/[\uFEFF]
The 'file' command shows if the BOM is present:
For example: 'file myfile.xml' displays: "XML 1.0 document, UTF-8 Unicode (with BOM) text, with very long lines, with CRLF line terminators"
dos2unix will remove the BOM.
I'm suggest the use of "dos2unix" tool, please test to run dos2unix ./thefile.js.
If necessary try to use something like this for multiple files:
for x in $(find . -type f -exec echo {} +); do dos2unix $x ; done
My Regards.
In windows you could use backported recode utility from UnxUtils.
In Sublime Text you can install the Highlighter package and then customize the regular expression in your user settings.
Here I added \uFEFF to the end of the highlighter_regex property.
{
"highlighter_enabled": true,
"highlighter_regex": "(\t+ +)|( +\t+)|[\u2026\u2018\u2019\u201c\u201d\u2013\u2014\uFEFF]|[\t ]+$",
"highlighter_scope_name": "invalid",
"highlighter_max_file_size": 1048576,
"highlighter_delay": 3000
}
To overwrite the default package settings place the file here:
~/.config/sublime-text-3/Packages/User/highlighter.sublime-settings
Save the file without code signature.

Resources