I have a collection of different static .html files. I want to recursively look through all .html files in the current folder and:
replace all instances of image.jpg with a user string.
replace all instances of textBlock1 with another user string.
replace all instances of textBlock2 with a third user string.
where image.jpg/ textBlock1/ textBlock2 are the only ones looked for exactly as written e.g. not tExtblock1
How do I accomplish this using terminal? Must work on a fresh macOS install.
Previous answers do not use user input See: Recursive search and replace in text files on Mac and Linux
This little bash script should do as you wish. Save it as modhtml and make it executable, just necessary one time, with:
chmod +x modhtml
and then you can run it with:
./modhtml
Here is the script:
#!/bin/bash
echo -n "Enter string1: "
read str1
echo -n "Enter string2: "
read str2
echo -n "Enter string3: "
read str3
echo DEBUG: str1=$str1
echo DEBUG: str2=$str2
echo DEBUG: str3=$str3
# Find all files (not directories), in the current directory and below...
# ... called "*.html" and, for each one, execute "sed" to change...
# ... image.jpg to str1
# ... textBlock1 to str2
# ... textBlock2 to str3
find . -type f -name \*.html -print -exec sed -e "s/image.jpg/$str1/g" -e "s/textBlock1/$str2/g" -e "s/textBlock2/$str3/g" {} \;
As it stands, it tells you the names of the files it would change and how they will look afterwards but doesn't actually change anything.
If it looks good - make a copy of your files first then run it for real by changing the last line to:
find . -type f -name \*.html -exec sed -i.bak -e "s/image.jpg/$str1/g" -e "s/textBlock1/$str2/g" -e "s/textBlock2/$str3/g" {} \;
If you want the user to be prompted for the string via a GUI-style prompt, rather than in the Terminal, replace the first few lines like this:
#!/bin/bash
str1=$(osascript -e 'Tell application "System Events" to display dialog "Enter string1:" default answer ""' -e 'text returned of result' 2>/dev/null)
str2=$(osascript -e 'Tell application "System Events" to display dialog "Enter string2:" default answer ""' -e 'text returned of result' 2>/dev/null)
str3=$(osascript -e 'Tell application "System Events" to display dialog "Enter string3:" default answer ""' -e 'text returned of result' 2>/dev/null)
echo DEBUG: str1=$str1
echo DEBUG: str2=$str2
echo DEBUG: str3=$str3
It will look like this:
Related
Whenever I execute this script it says: no such file or directory.
I'm not sure what I'm doing wrong here. I put quotes around it just in case if there is a space in the directory's name.
#!/bin/bash
read -p "Enter destination: " folder
folder=$(sed -e 's/^/"/' -e 's/$/"/' <<< $folder)
cd $folder
It is better to use quotes in the cd command, regardless of whether the directory has spaces or not, like this:
#!/bin/bash
read -p "Enter destination: " folder
cd "$folder"
pwd
Test:
Another solution (use with caution as it may cause other problems) is using eval in your code:
#!/bin/bash
read -p "Enter destination: " folder
folder=$(sed -e 's/^/"/' -e 's/$/"/' <<< $folder)
eval cd $folder
References:
Bash script to cd to directory with spaces in pathname
There is this solved topic about opening .html files via command line.
I use the solution and it works well for using
open ./myfile.html
However, it opens the file always in a new tab. I would like to open it always in the same tab (using the browser target). This is an easy thing to do in JavaScript, but I can't figure out a way to do it in combination with the above mentioned code.
My assumption for now is, that there must be a way to pass the target as a parameter to the open command. The man open reveals the following for the parameter --args:
All remaining arguments are passed to the opened application in the
argv parameter to main(). These arguments are not opened or
interpreted by the open tool.
So I tried the following:
open ./myfile.html --args target=myfile_target # still opens in new tab
open ./myfile.html --args target="myfile_target" # still opens in new tab
open ./myfile.html --args target:myfile_target # still opens in new tab
I am not sure if this even works but I think there must be a way to do this.
Edit: for now it is enough to make this work with chrome.
This Bash script incorporates a bit of AppleScript in order to open a browser window with a reference that the script can keep track of and continue to target with ongoing URL requests.
You ought to be able to copy-n-paste it into a text editor and save it as whatever you wish to call this replacement open function. I saved it as url, in one of the directories listed in my $PATH variable. That way, I could simply type url dropbox.com from the command-line, and it would run.
You will have to make it executable before you can do that. So, after it's saved, run this command:
chmod +x /path/to/file
Then you should be good to go. Let me know if you encounter any errors, and I'll fix them.
#!/bin/bash
#
# Usage: url %file% | %url%
#
# %file%: relative or absolute POSIX path to a local .html file
# %url%: [http[s]://]domain[/path/etc...]
IFS=''
# Determine whether argument is file or web address
[[ -f "$1" ]] && \
_URL=file://$( cd "$( dirname "$1" )"; pwd )/$( basename "$1" ) || \
{ [[ $1 == http* ]] && _URL=$1 || _URL=http://$1; };
# Read the value on the last line of this script
_W=$( tail -n 1 "$0" )
# Open a Safari window and store its AppleScript object id reference
_W=$( osascript \
-e "use S : app \"safari\"" \
-e "try" \
-e " set S's window id $_W's document's url to \"$_URL\"" \
-e " return $_W" \
-e "on error" \
-e " S's (make new document with properties {url:\"$_URL\"})" \
-e " return id of S's front window" \
-e "end try" )
_THIS=$( sed \$d "$0" ) # All but the last line of this script
echo "$_THIS" > "$0" # Overwrite this file
echo -n "$_W" >> "$0" # Appened the object id value as final line
exit
2934
I have written a code but I am having a problem to make the double loop in my bash script. This script should read all the files 1 by 1 in the given directory to upload but the value of "XYZ" changes for each file. Is there a way for me to make the code ask me to enter the "XYZ" every time it reads a new file to upload? (if possible with the name of the file read) like "please enter the XYZ value of 'read file's name'" I could not think of any possible ways of doing so. I also have the XYZ values listed in a file in a different directory so maybe can it be called like the do loop I did for the path? I might actually need to use both cases as well...
#!/bin/bash
FILES=/home/user/downloads/files/
for f in $FILES
do
curl -F pitch=9 -F Name='astn' -F
"path=#/home/user/downloads/files;$f" -F "pass 1234" -F "XYZ= 1.2" -
F time=30 -F outputFormat=json
"http://blablabla.com"
done
try following once.
#!/bin/bash
FILES=/home/user/downloads/files/
for f in $FILES
do
echo "Please enter the name variable value here:"
read Name
curl -F pitch=9 -F "$Name" -F
"path=#/home/user/downloads/files;$f" -F "pass 1234" -F "XYZ= 1.2" -
F time=30 -F outputFormat=json
"http://blablabla.com"
done
I have entered a read command inside loop so each time it will prompt user for a value, since you haven't provided more details about your requirement so I haven't tested it completely.
The problem was actually the argument. By changing it to:
-F Name="$Name"
solved the problem. Trying to link the argument such as only $Name or "$Name" causes a bad reception.
What i need to do is replace the folder amtlib.framework into each Adobe app on my mac
if i do:
cd /Applications; ls | grep Adobe, this gives me all the folders which i need
here's some pseudo code:
apps = ls | grep Adobe
for each x in apps
if (x/x.app/contents/frameworks/amtlib.framwork) //if this folder exists
add .bak extension //amtlib.framework.bak
copy ~/Downloads/.../amtlib.framwork to x/x.app/contents/frameworks/
how would i implement this as a bash script?
Something like
for x in $( ls | grep Adobe) ; do
if [[ -d "${x}"/"${x}".app/contents/frameworks/amtlib.framwork ]] ; then
# add .bak extension # //amtlib.framework.bak
#? mkdir "${x}"/"${x}".app/contents/frameworks/amtlib.framwork.bak
#? /bin/mv "${x}"/"${x}".app/contents/frameworks/amtlib.framwork {x}/${x}.app/contents/frameworks/amtlib.framwork.bak
/bin/cp ~/Downloads/.../amtlib.framwork to "${x}"/"${x}".app/contents/frameworks/
else
: # ??? what do you want to do if there's not
fi
done # loop
If you're likely to have spaces in your dirnames, (not sure if OSX support -print0), but try
find . -name 'Adobe' -print0 \
| while read x ; do
if ....
As an FYI, assignments in bash are done like (without spaces around the =):
apps=$(ls | grep Adobe)
Depending on the situation then, you'll want to use "$apps", or just plain $apps, which leaves each word in the list as a separate token. (If there are spaces in your filename or path, 1 path/file is now 2 words, and will cause issues). There are also array notations to use, apps=( $(ls | grep Adobe) ), and using those vars like ${#apps[#]} (number of elems), ${apps[#]} (all elems), ${apps[1]}, (first elem) is possible.
Also, it's not clear what your intent with add .bak extension is for. My best guess is my 2nd option, /bin/mv ... .bak.
IHTH.
First of all there's a typo error in the original post that's made its way throughout the examples given. The folder you are looking to rename/replace is amtlib.framework, not framwork.
Second, for some reason, the test for existence of the .bak directory is not working for me, even when I split this out to a separate if-then statement it doesn't work:
cd /Applications
for x in *Adobe* ; do
printf "$x \n"
printf "%s" " "
if [ -d "$x/$x.app/contents/frameworks/amtlib.framework.bak" ]; then
printf "removing old bak... "
fi
if [ -d "$x/$x.app/contents/frameworks/amtlib.framework" ]; then
printf "moving... "
printf "copying... "
printf "%s\n" "done!"
else
printf "%s\n" "nothing to do here!"
fi
done
cd ~
Finally, understanding the goal you will fail to update a couple of apps that have an additional folder level (e.g., Acrobat Pro and Illustrator).
I am writing a shell script that prompts the user for a file path:
read -e -p "Enter the path to the file: " FILEPATH
I am then using this file path to perform operations – namely to compress a folder.
(cd "$FILEPATH"; tar -cvz *) > /tmp/torrent.tar.gz;
At the prompt, if I use the ~ alias (home directory), then the shell script doesn't seem to understand this, as the tar function compresses the wrong path. Is there anyway I can allow for this alias?
Also, tab completion seems to be case-sensitive at the prompt. I was wondering how I can change that?
Example using eval:
read -e -p "Enter the path to the file: " FILEPATH
eval FILEPATH=$FILEPATH
cd $FILEPATH
echo $PWD
In your case it becomes:
read -e -p "Enter the path to the file: " FILEPATH
eval FILEPATH=$FILEPATH
(cd "$FILEPATH"; tar -cvz *) > /tmp/torrent.tar.gz;
To deal with spaces you can use sed:
read -e -p "Enter the path to the file: " FILEPATH
FILEPATH=$(echo $FILEPATH | sed 's/ /\\ /')
eval FILEPATH=$FILEPATH
cd "$FILEPATH"
echo $PWD
You could apply the substitution yourself like this:
filepath=${filepath/\~/$HOME}
I don't know whether there's a way to get the shell to do it for you.
Here's an answer to your other question: https://superuser.com/questions/90196/case-insensitive-tab-completion-in-bash