I use this as str_replace for every file in folder after unzipng archive in temp folder

find "$tmp" -type f | xargs sed -i "s/${targetsubstring}/${newsubstring}/g"

but I get this error:

sed: can't read /tmp/tmp.Q18p8BRYcc/steam: No such file or directory
sed: can't read engine.txt: No such file or directory

My tmp var:

tmp=mktemp -d

What am I doing wrong?


archive=`readlink -e $1` #First param is tar archive without file structure (only text files inside)
targetsubstring=$2 #Substring to replace
newsubstring=$3 #Substring to replaced by
tmp=`mktemp -d` #Create a room to unzip our archive

if [ -f "$archive" ]; #Check if archive exist
    echo "Well done! (And yeah, I know about [ ! -f '$1' ], but where would be the fun?)" >/dev/null
    echo "File doesn't exist! Terminating program." >&2
    exit 1
tar xvf "$archive" -C "$tmp" >/dev/null #Unzip archive to temp folder
find "$tmp" -type f | xargs sed -i "s/${targetsubstring}/${newsubstring}/g" #For every file do str_replace (There is a problem somwhere)
cd  "$tmp" 
tar -zcf "$archive" .  #Zip this to original file (I don't want any folder in my tar file)
  • 2
    Could you explain what it is that you are trying to do? I only understand these parts: 1) Make a DIRECTORY. 2) Look for FILES only. 3) Put this empty collection though to sed using a pipe. – Hennes Nov 17 '13 at 14:17
  • What does find "$tmp" -type f list? What do you expect it to return? Maybe, as @Hennes said, include the full script and explain what the purpose is. – slhck Nov 17 '13 at 14:35
  • Code updated!.. – JohnDow Nov 17 '13 at 15:27

Oh dear, you're a victim of the most terrible thing in the world: you looked on the internet to find snippets of shell-scripting, you found a lot of them, but you were never told that most of them are completely broken. Most of them break if they encounter file names with spaces in them.

This is typically the case of all the scripts that parse the output of a command designated to output information readable by humans, e.g., find or ls.

In your case, you have the file /tmp/tmp.Q18p8BRYcc/steam engine.txt that contains a space and that breaks your command.

Please consider using find properly, with its -exec switch:

find "$tmp" -type f -exec sed -i "s/${targetsubstring}/${newsubstring}/g" {} \;

In this case, find will -execute the part

sed -i "s/${targetsubstring}/${newsubstring}/g" {}

with the place-holder {} replaced by the found file names... but replaced properly in a way it can't bbreak if the file name contains spaces, newlines or other funny symbols. Well, it might break if {} happens to be replaced by something that starts with a hyphen (but that is unlikely, unless the variable $tmp expands to such a thing); in this case,

sed -i "s/${targetsubstring}/${newsubstring}/g" -- {}

will do, if your sed version supports the -- option of course.

You could replace the trailing \; (that means end of arguments of command to execute) by + so that sed will be launched with as many arguments it can handle, so it will not be spawned once per file.

Yet, there's another way to use find safely with xargs, using the -print0 option of find and the -0 option of xargs:

find "$tmp" -type f -print0 | xargs -0 sed -i "s/${targetsubstring}/${newsubstring}/g"
  • Thank you so much! Now I see whats wrong with my script, and now I see a case, when this archive name can contain space too! (Like bash.sh "/tmp/tmp.uzIycPFQIL/work/data txt" a A) – JohnDow Nov 17 '13 at 15:35

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.