0

So, I'm aware of that this topic has been discussed in several ways, but the responses didn't work for me.

I'm using sed to remove a line from a script, but each time I execute the bash script, I receive an error message "No such file or directory". I'm able run the command from the remote host terminal. See the sed command below.

#!/bin/bash

declare server_list="/location/of/iplist.txt"
declare file="/location/of/file/to/modify"
declare regex='"/\export JAVA_HOME=\/jvm\/home\/directory\/java/d"'
declare file_content="$(sudo grep -Fxq export 
JAVA_HOME=/java/home/directory/java "${file}" )

declare script="sudo sed -i -e ${regex} ${file}"

date
cat ${server_list} |  while read server
do
# connect to each server and execute the "sed -i" command
ssh -I /location/of/pub/key ${server} -o StrictHostKeyChecking=no

# read file content into condition statement
${file_content}
if [ $? -eq 0 ];
then
    # confirm string exist and remove the line
    echo "JAVA_HOME located on ${server}"
    "${script}"
else
    echo "No JAVA_HOME located on ${server}"
fi
done
user3593238
  • 9
  • 1
  • 2
  • put your file, where you are trying to change – Incrivel Monstro Verde Nov 20 '18 at 14:46
  • 1
    You might do well to put a -e after the -i. The -i parameter can take an option - the suffix to add to the backup file. In the case above, you may be telling sed that the file you want to modify is called "/\export\ \JAVA_HOME=\/usr\/lib\/jvm\/java/d", which of course it can't find. One more suggestion is to put your sed commands into a file and the use the sed -f > first, before playing with the -i option. – Mark Nov 20 '18 at 14:50
  • Your script has an entire command line quoted somewhere, as if you had typed `'sudo sed -i "/\export\ \JAVA_HOME=\/usr\/lib\/jvm\/java/d"'` at the prompt instead of `sudo sed -i "/\export\ \JAVA_HOME=\/usr\/lib\/jvm\/java/d"`. – chepner Nov 20 '18 at 14:54
  • @chepner Thank you for your response. I modified the script, but the error still exist. "No such file or directory" – user3593238 Nov 20 '18 at 16:19
  • On a tangent: It looks like you've got a shipment of slashes and backslashes and they are all mixed up in transit. Do you know you can use *any* character as the sed command delimiter? `sed -i "#export JAVA_HOME=/usr/lib/jvm/java#d"` is somewhat more readable.. – n. m. could be an AI Nov 20 '18 at 16:41
  • 1
    @user3593238 You are quoting `$script`. See [I'm trying to put a command in a variable, but the complex cases always fail!](https://mywiki.wooledge.org/BashFAQ/050). – chepner Nov 20 '18 at 16:55
  • I just tried to execute the script and I received the same error. `line 22: sudo sed -i #export JAVA_HOME=/usr/lib/jvm/java#d /etc/init.d/jboss: No such file or directory` – user3593238 Nov 20 '18 at 16:55
  • Also see [How to use Shellcheck](http://github.com/koalaman/shellcheck), [How to debug a bash script?](http://unix.stackexchange.com/q/155551/56041) (U&L.SE), [How to debug a bash script?](http://stackoverflow.com/q/951336/608639) (SO), [How to debug bash script?](http://askubuntu.com/q/21136) (AskU), [Debugging Bash scripts](http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html), etc. – jww Nov 21 '18 at 18:03

2 Answers2

0

Don't put complete commands in variables. "${script}" is an invitation for trouble.

An illustrative example:

me ~ > echo -e 'foo bar\nbaz qux' > /tmp/foobar

me ~ > cat /tmp/foobar
foo bar
baz qux

me ~ > sed -e '/foo bar/d' /tmp/foobar
baz qux

me ~ > cmd="sed -e '/foo bar/d' /tmp/foobar"

me ~ > $cmd
sed: -e expression #1, char 1: unknown command: `''

me ~ > ${cmd}
sed: -e expression #1, char 1: unknown command: `''

me ~ > "$cmd"
bash: sed -e '/foo bar/d' /tmp/foobar: No such file or directory

me ~ > "${cmd}"
bash: sed -e '/foo bar/d' /tmp/foobar: No such file or directory

What's going on here? If you use $cmd unquoted, sed has following 4 arguments:

  • -e
  • '/foo
  • bar/d'
  • /tmp/foobar

(yes that's how "words" in bash work). Obviously sed cannot interpret this gibberish.

If you try running "$cmd" or "${cmd}", the entire string is interpreted as the command name, spaces quotes and all. The shell complains it cannot find an executable file named sed -e '/foo bar/d' /tmp/foobar, and it's absolutely right. No good either.

Solution?

A quick and dirty hack is

me ~ > eval ${cmd}
baz qux

Works as expected! However, eval is dangerous and should not be used unless you are a certified shell guru. (Which you, I believe, still are not). A better option is to define a function.

cmd() {
    sed -e '/foo bar/d' /tmp/foobar
}

...

cmd
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
0

Try to use eval to execute variable content

declare file="/location/of/file/to/modify"
declare regex='"/\export JAVA_HOME=\/jvm\/home\/directory\/java/d"'
declare script="sudo sed -i -e ${regex} ${file}"
eval ${script}
  • Okay. When I execute the script it returns this error: `regex='"/\export JAVA_HOME=\/jvm\/home\/directory\/java/d"'` `sed: 1: "JAVA_HOME=/usr/lib/jvm/ ...": invalid command code J` When I removed the regular expressions, I get this: `regex='"/export JAVA_HOME=\jvm\home\directory/java/d"' `sed: 1: "/export": unterminated regular expression ` – user3593238 Nov 21 '18 at 16:25