Yarin
Yarin

Reputation: 183589

Just got bashed by my sed script- why?

Based on the helpful answers I received here, I created the following script, named it convert_image_paths.command, put it in a website folder on my mac and double-clicked it.

#!/bin/bash

# This script will operate on valid relative image paths at this level and one sub-level down, across .html and .css files.

find . -name "*.css" -o -name "*.html" -exec sed -i '' 's/\.\.\/images\//images\//g' {} ';'
find . -name "*.css" -o -name "*.html" -exec sed -i '' 's/images\//http:\/\/mycdn\.com\/images\//g' {} ';'

Unfortunately, instead of changing the relative image paths in the website to the new cdn url, it

  1. Doubled up the url: http://mycdn.com/http://mycdn.com/images/myimage.png
  2. Did that for EVERY html/css file on my machine

So my question is a) is there a tag for moron and b) how do I fix this script?

EDIT:

Let me clarify my intention: I wanted to apply the change to all image paths with relative urls in the form

"image/{myimagepath}"

or

"../images/{myimagepath}"

Upvotes: 0

Views: 169

Answers (3)

Yarin
Yarin

Reputation: 183589

I also figured out why my original script did not recognize it's current directory. On macs, if you name a script file with the .command extension, it becomes double-clickable. However, when you execute it with a double-click, instead of from the command line, it changes its working directory to the users home directory!

myscript.command:

echo "pwd = `pwd`"

./myscript.command : pwd = current directory

myscript.command double-clicked : pwd = User home directory

Upvotes: 1

Cascabel
Cascabel

Reputation: 496962

find . means "find in the current directory" - so be sure to run this from a directory in which you want to make this substitution in all contents, or change the script to take arguments:

#!/bin/bash
if [ $# -lt 1 ]; then
    echo "usage: myscript <path>"
fi

find "$@" ...

My guess about why things got doubled is simply that it was run twice; that second substitution in your original script will see "http://mycdn.com/images" and substitute for images again! Here's the obvious way to combine the two substitutions and fix that problem at the same time:

sed -i 's@"\(\.\./\|\)images/@"http://mycdn.com/images/@g'

Match against the open quote to make sure you don't substitute when there's already an http://..., and optionally match a ../ after it.

I would definitely suggest testing by invoking this on a single file, with results printed to stdout instead of editing in place:

sed 's@...@...@' <file>

Upvotes: 1

Paul Tomblin
Paul Tomblin

Reputation: 182782

To answer your second question:

b) Don't do "find ." when you don't know what directory the script is starting from. If you want it to start from a particular directory, tell it in the find command: find /Users/ptomblin/Shared/ ...

As for why it doubled up the URL, it's because you told it to.

sed -i '' 's/images\//http:\/\/mycdn\.com\/images\//g' {}

Takes every instance of the word "images/" and changed it to "http://mycdn.com/images/", even if it already started with "http://mycdn.com/". If that's not what you wanted, you're going to have to be more specific about your regexp.

As a first attempt, I would replace BOTH lines with the following

find /Users/ptomblin/Shared -name "*.css" -o -name "*.html" -exec sed -i '' 's@".{0,2}/?images@"http://mycdn.com/images@g' {}

That will only replace images or ../images if they start with a double quote.

Upvotes: 4

Related Questions