I need to go through all my css and js files and if there is a filename referenced that has any slashes (/) at all then the slash should be removed.

What I want is:

  • if any files referenced are named /file.jpg then remove the leading slash leaving just file.jpg.

    For example, in a CSS file change:

    @import url("/base.css"); to @import url("base.css");

  • if the file referenced is named /files/file.jpg then the leading slashes and folder name should be removed leaving just file.jpg.

I started to write it but then couldn't think about how to deal with the slashes.

grep -o -h -E '[A-Za-z0-9:./_-]+\.(png|jpg|gif|tif|css)' `find
${new_directory} -name '*.css' -or -name '*.js'`

Any idea how to do this? I am doing this using a .sh shell script.

  • ouch. that's nasty. I don't think I want to know how you ended up with that situation! :-o – Spudley Jul 12 '11 at 13:45
  • See stackoverflow.com/questions/965053/… – Ray Toal Jul 12 '11 at 13:46
  • Hmm...I think quite a few people have gotten the wrong end of the stick here. If I read this correctly, the question isn't about changing filenames on the filesystem, but filenames referenced in the CSS and javascript files themselves. – Kev Jul 12 '11 at 17:24

Don't parse the output of find that way. It'll work if your files don't contain any special characters, but to invoke a command on the files found by find, it's easier and more robust to make find call the command:

find "$new_directory" -name '*.css' -o -name '*.js' -exec grep … {} +

Then grep isn't the right tool to perform a text replacement; it's only a search tool. sed is a stream editor, and its most widely used feature is regexp replacement. Assuming GNU sed (such as found on Linux), and assuming that your regexp is basically correct, i.e. that you want to match all sequences of letter-or-digit-or-:._- followed by a likely-looking extension as file names, here's a sed call to replace DIR1/DIR2/FILE.EXT by FILE.EXT everywhere:

sed -e 's![/A-Za-z0-9:._-]*/\([A-Za-z0-9:._-]*\.\(png\|jpg\|gif\|tif\|css\)\)!!g'

Putting both pieces together, if you want to make the replacements in place, the easiest way is to use GNU sed's -i option, which does just that.

find "$directory" -name '*.css' -o -name '*.js' \
     -exec sed -e 's![/A-Za-z0-9:._-]*/\([A-Za-z0-9:._-]*\.\(png\|jpg\|gif\|tif\|css\)\)!!g' {} +

If you want to put the replacements in a different place, you'll need a bit of intermediate shell glue to construct the names of the new files.

find "$old_directory" -name '*.css' -o -name '*.js' \
     -exec sh -c 'sed -e '\''s![/A-Za-z0-9:._-]*/\([A-Za-z0-9:._-]*\.\(png\|jpg\|gif\|tif\|css\)\)!!g'\' <"$0" >"/new/directory/$0"' {} \;

Note the use of '\'' to put a single quote inside the single-quoted shell snippet. -exec … {} \; means to run the command once on each file, in contrast with -exec … {} + which runs the command on as many files in one batch as possible.

| improve this answer | |

Use the basename built-in. It works like this:

$ basename "/abc/def/ghi.jkl"
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy