How to overwrite the contents in the sed, without having backup file - macos

I have a command like this:
sed -i -e '/console.log/ s/^\/*/\/\//' *.js
which does comments out all console.log statements. But there are two things
It keeps the backup file like test.js-e , I doesn't want to do that.
Say I want to the same process recursive to the folder, how to do it?

You don't have to use -e option in this particular case as it is unnecessary. This will solve your 1st problem (as -e seems to be going as suffix for -i option).
For the 2nd part, u can try something like this:
for i in $(find . -type f -name "*.js"); do sed -i '/console.log/ s/^\/*/\/\//' $i; done;
Use find to recursively find all .js files and do the replacement.

When checking sed's help, -i takes a suffix and uses it as a backup,
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if SUFFIX supplied)
and the output backup seems to be samefile + -e which is the second argument you're sending, try removing the space and see if that would work
sed -ie '/console.log/ s/^\/*/\/\//' *.js
As for the recursion, you could use find with -exec or xargs, please modify the find command and test it before running exec
find -name 'console.log' -type f -exec sed -ie '/console.log/ s/^\/*/\/\//' *.js \;

From your original post I presume you just want to make a C-style comment leading like:
/*
to a double back-slash style like:
//
right?
Then you can do it with this command
find . -name "*.js" -type f -exec sed -i '/console.log/ s#^/\*#//#g' '{}' \;
To be awared that:
in sed the split character normally be / but if you found that annoying to Escape when your replacing or matching string contains a / . You can change the split character to # or | as you like, I found it very useful trick.
if you do want to do is what I presumed, be sure that you should Escape the character *, because a combination of regex /* just means to match a pattern that / occurs one time or many times or none at all, that will match everything, it's very dangerous!

Related

How to correctly combine find, sed & tr to replace a newline in all my files

All of my PHP files currently start
<?php
declare(strict_types=1);
It's a minor thing, but I'd like to change them all to
<?php declare(strict_types=1);
I think I need to use tr as sed works on a single line at a time. But I can't come up with the right command to recursively do this through a directory of .php files.
Thanks!
You can try that out with GNU sed:
find . -name *.php -exec sed -i '1{N;s/<?php\s*\n\s*declare/<?php declare/}' {} \;
The find bit retrieves all .php files in the current directory, the sed bit edits them in-place to change a matched two-line definition into a one-line definition.
It assumes the php opening tag is in the first line, and looks for a second line starting with declare (and optional spaces).
If you don't use GNU sed, this command should be posix compliant :
find . -name *.php -exec sed -i.bak '1{N;s/<?php[[:space:]]*\Enter[[:space:]]*declare/<?php declare/}' {} \;
However it also creates backups of the .php files, which can be removed once sure of the success of the command with an additional find :
find . -name *.php.bak -delete

using find with variables in bash

I am new to bash scripting and need help:
I need to remove specific files from a directory . My goal is to find in each subdirectory a file called "filename.A" and remove all files that starts with "filename" with extension B,
that is: "filename01.B" , "filename02.B" etc..
I tried:
B_folders="$(find /someparentdirectory -type d -name "*.B" | sed 's# (.*\)/.*#\1#'|uniq)"
A_folders="$(find "$B_folders" -type f -name "*.A")"
for FILE in "$A_folders" ; do
A="${file%.A}"
find "$FILE" -name "$A*.B" -exec rm -f {}\;
done
Started to get problems when the directories name contained spaces.
Any suggestions for the right way to do it?
EDIT:
My goal is to find in each subdirectory (may have spaces in its name), files in the form: "filename.A"
if such files exists:
check if "filename*.B" exists And remove it,
That is: remove: "filename01.B" , "filename02.B" etc..
In bash 4, it's simply
shopt -s globstar nullglob
for f in some_parent_directory/**/filename.A; do
rm -f "${f%.A}"*.B
done
If the space is the only issue you can modify the find inside the for as follows:
find "$FILE" -name "$A*.B" -print0 | xargs -0 rm
man find shows:
-print0
True; print the full file name on the standard output, followed by a null character (instead of the newline character that -print uses). This allows
file names that contain newlines or other types of white space to be correctly interpreted by programs that process the find output. This option corre-
sponds to the -0 option of xargs.
and xarg's manual
-0 Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literal-
ly). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or
backslashes. The GNU find -print0 option produces input suitable for this mode.

Substitute string in BASH with Sed (when it has special characters)

It's a fairly simple question and I'm sure the gurus here can figure it out right away, however I don't seem to be able to make it work (probably some quotes issue.
I want to place all instances of:
`which cat`
With the following:
/bin/cat
I am running the following command:
for file in $(find . -iname 'PATCH*'); do sed 's/\`which cat\`/\'\/bin\/cat/g' $file; done
I believe I have escaped all characters that don't need to be treated as special ones, however it doesn't seem to do the trick.
Please help :)
It is generally not a good idea to iterate over the output of find since file names can contain the $IFS which would break the loop. Use the -exec option of find instead:
find -iname 'PATCH*' -exec sed -i 's#`which cat`#/bin/cat#g' {} \;
Use a different sed delimiter.
sed 's~`which cat`~/bin/cat~g' file
Example:
$ echo '`which cat`' | sed 's~`which cat`~/bin/cat~g'
/bin/cat

Sed over BASH escaping

I am looking to go through our site and remove the encoded hard paths and replace them with $_SERVER['DOCUMENT_ROOT'] over a shell connection, but I am not sure how to escape it correctly.
Need to replace
"/home/imprint/public_html/template
With
$_SERVER['DOCUMENT_ROOT']."/template
Here is what I found to do it, but I also need to include .htm files and I am not sure what I need to escape.
find . -name '*.php' -exec sed -i 's/"/home/imprint/public_html/template/$_SERVER['DOCUMENT_ROOT']."/template/g' {} \;
Also, what does the -i option do in sed?
You can combine find clauses with -o ("or")
If you use different delimiters for the sed s command, you don't need to escape anything.
search='"/home/imprint/public_html/template'
replace='$_SERVER['DOCUMENT_ROOT']."/template'
find . -name '*.php' -o -name '*.htm' \
-exec sed -i "s#${search}#${replace}#g" {} +
To gain efficiency by reducing the number of times sed is invoked, use -exec ... + instead of -exec ... \;
If you're replacing a fixed string with another one, you can use sed with single quotes rather than doubles, as it will prevent any interpretation of the $ sign or other unpredicted funkiness.
Also since you're replacing pathes, fyi you can use other chars than / as sed's delimiter (i.e. sed "s=abc=def=g"), which is probably clearer.
From the man page :
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if extension supplied)
Maybe you can try the next
shopt -s globstar
perl -i.bak -pe 's:/home/imprint/public_html/(template):\$_SERVER['DOCUMENT_ROOT']/$1:' ./**/*.php
will create backup file .bak
the ./**/*.php will search for all php files recusively if the globstar option is set

command line script to indent

I am looking for a simple command line script or shell script I can run that, with a given directory, will traverse all directories, sub directories and so on looking for files with .rb and indent them to two spaces, regardless of current indentation.
It should then look for html, erb and js files (as well as less/sass) and indent them to 4.
Is this something thats simple or am I just over engineering it? I dont know bash that well, I have tried to create something before but my friend said to use grep and I am lost. any help?
If you've got GNU sed with the -i option to overwrite the files (with backups for safety), then:
find . -name '*.rb' -exec sed -i .bak 's/^/ /' {} +
find . -name '*.html' -exec sed -i .bak 's/^/ /' {} +
Etc.
The find generates the list of file names; it executes the sed command, backs up the files (-i .bak) and does the appropriate substitutions as requested. The + means 'do as many files at one time as is convenient. This avoids problems with spaces in file names, amongst other issues.

Resources