# Problem under Linux executing bash script:
# After making sure that the script as "scriptpath" is there,
# I run

var output = []
var res = OS.execute( "bash", [scriptpath], true, output)

# and get the following error: 127 (= file not found)

# I think: OK, bash is somehow missing. But I know it is under
# "/bin/bash". However, replacing plain old "bash" with 
# "/bin/bash" doesn't help.

# I am wondering it I don't understand something about using
# OS.execute, so I try some other Linux program by comparison, and:

res = OS.execute( "file", [scriptpath], true, output)

# returns 0 (expected value), so scriptpath is there.
# It is apparently not finding bash. To test this, I try

result = OS.execute( "bash", ["--help"], true, output)

# and it works! So bash is there, too, just not in combination
# with my script.

# It dawns on me that the bash script may not be executable?
# So I run a previous chmod on it, like this:
res = OS.execute( "chmod", ["u+x", scriptpath], true, output)
# which is successful, followed immediately in my code by
res = OS.execute( "bash", [scriptpath], true, output)

# and still: no dice.

# Now it dawns on me: Since the script is now executable, I don't
# need to call bash first, but just call the script, like this:
res = OS.execute( scriptpath, [], true, output)
# nope! Likewise:
res = OS.execute( scriptpath, [""], true, output)

# I am at the end of my wits here. Any help?

Sorry about the huge text. I learned: Don't copy in in comment lines starting with hash sign! The content of my script is as follows: cd "/home/joe/godot"; 7zr a "/home/joe/godot/test.7z" "/home/joe/godot/test.txt" -mx9 The script works fine in a Linux terminal, essentially 7-zipping test.txt in-place as test.7z, which is what I want to accomplish.

@schnoof said: Sorry about the huge text. I learned: Don't copy in in comment lines starting with hash sign!

No worries, I fixed it for you by telling the forums to render it as a code block (added three ~ to each side). Also: Welcome to the forums :smile:

I'm not on Linux so can't really test much, but based on this from the docs: Os.execute ( String path, PoolStringArray arguments, bool blocking=true, Array output=[ ], bool read_stderr=false )

I suspect your command should look like this: var res = OS.execute( scriptpath, [], true, output) Can you confirm what the error was from this? If this still does not work, could be Godot expects a Shebang or scriptpath is malformed or for some reason unreachable (permissions perhaps, though I would 'assume' the Godot executable runs as the user and not it's own ting)? Also it could be related to this (single/double quoting) issue: https://github.com/godotengine/godot/issues/37291

Alternatively, I think (untested) you could just do this instead: OS.execute("7zr", ["a", "'/home/joe/godot/test.7z'", "'/home/joe/godot/test.txt'", "-mx9"], true, output) The cd shouldn't be necessary as you're already specifying the full directory string in the command. Sidenote though, this will only work on your machine if you hardcode the path, so would suggest using Godot's user directory as a relative path if you ever plan to export it.

Thanks all, I set up a new project to isolate my problem and got the following running, so it appears that my problems lie in my actual project and outside of OS.Execute(). Note that I am not (expressly) calling bash at all, but rather my executable script (Line 73).

(sample usage)

func _ready():
	           sevenzip_me_linux(true, "/home/joe/test.txt")

 ===  FUNCTION  ================================================================
  NAME:         sevenzip_me_linux()
  PURPOSE:      pack or unpack single files in-place using 7-zip (7zr) (Linux)
  ASSUMED:    The application 7zr is installed on the Linux machine
  EXPECTED:     
 				pack: (true or false) If true, compress, otherwise decompress
 				inpath: the full path of the file as source
 				outpath: 
 					When packing, this is the full path of the resulting, 
 					compressed file. If not provided, ".7z" will be added to the
 					variable inpath to determine the path of the resulting file.
 					Not required when unpacking.
 
  RETURN VALUE: error code (an integer)
 				0 means success.
 				 -1 means error caught by my own code.
  KNOWN ISSUES:	Uses a temporary bash script under ~/Downloads/7zSKRIPT.bsh
 				as a demonstration here of executing bash scripts.
 				This causes overhead that may be proven unnecessary, as direct
 				calls to OS.Execute() with the correct parameters may be more
 				efficient.
 				Seven-zipping small files (hundreds of bytes or so) typically
 				returns a larger file, as the 7-zip container includes some
 				overhead itself. Also, 7-zipping already compressed file types
 				might return in a larger file. No logic is provided here for
 				testing and handling such cases.
 ==============================================================================

    func sevenzip_me_linux(pack : bool, inpath : String, outpath="") -> int:
    
    	var res = 1 # a variable for the return value. Value will be replaced.
    	var output = [] # a dummy needed for syntax of OS.execute() calls
    	
    	var dir = Directory.new()
    	if not dir.file_exists(inpath):
    		print("Source for 7-zipping does not exist. inpath = " + inpath)
    		return -1
    
    	# Create a script under ~/Downloads. I will delete it before returning.
    	# I suppose I could put the script anywhere, but choose ~/Downloads here.
    	var scriptpath = ""
    	var dl = OS.get_system_dir(3) # is ~/Downloads, at least on Linux Mint
    	scriptpath = dl + "/7zSKRIPT.bsh" # (an arbitrary name for the script)
    	
    	# ASSUMED: it is necessary to change the directory up-front when 7-zipping
    	# in-place. So determine the parent directory of the file I am going
    	# to 7-zip (here: inpath)
    	var parent_dir = ""
    	var diskpathchop = [] # chop the path up into parts along "/"
    	diskpathchop = inpath.split("/")
    	var basename = diskpathchop[diskpathchop.size() - 1]
    	# -1 here to get rid of the trailing "/"
    	parent_dir = \
    	str(inpath).left(str(inpath).length() - basename.length() - 1)
    
    	# set-up the code of the bash script, starting with the shebang and
    	# following line feed
    	var bash_code = "#!/bin/bash\n"
    	# change the directory before 7-zipping in-place (see above), add a
    	# semi-colon, as bash needs a ; between commands on same line
    	bash_code += "cd \"" + parent_dir + "\"; "
    
    	if pack: # (packing mode)
    		if outpath == "":
    			# Since no name for the resulting .7z file was provided (outpath),
    			# just add ".7z" to the inpath and you have the path
    			outpath = inpath + ".7z"
    		if dir.file_exists(outpath): # It will hopefully not be there!
    			print("Target of packing already exists. outpath = " + outpath)
    			return -1
    			
    		# add the command for seven-zipping to the bash script:
    		var sevenzipcommand = "7zr" + " " + \
    			"a" + " " + "\"" + outpath + "\"" + " " + \
    			"\"" + inpath + "\" -mx9"
    		bash_code += sevenzipcommand
    		
    	else: # (un-packing mode)
    		if dir.file_exists(outpath): # It will hopefully never be there!
    			print("Target of unpacking already exists. outpath = " + outpath)
    			return -1
    			
    		# add the command for seven-zipping to the bash script:
    		var sevenzipcommand = "7zr" + " " + \
    		"e" + " " + "\"" + inpath + "\"" + " " + \
    		"-o" + "\"" + parent_dir + "\"" # NO space between -o and following "
    		bash_code += sevenzipcommand
    
    	# write the script to disk
    	var f = File.new()
    	f.open(scriptpath, f.WRITE)
    	f.store_line(bash_code)
    	f.close()
    	
    	# check if script was written
    	if dir.file_exists(scriptpath):
    		# Make the script executable. TESTED and found necessary.
    		OS.execute( "chmod", ["u+x", scriptpath], true, output)
    
    		# Execute the script.
    		res = OS.execute( scriptpath, [], true, output) # recommended by forum
    		print("7z-result = " + str(res))
    		
    		if res == 0: # = successful execution of script
    			dir.remove(scriptpath) # get rid of the script
    			
    			# Comment this out if you want to keep the original
    			if pack:
    				dir.remove(inpath) # You are seven-zipping to save space, right?
    		
    	else:
    		print("script not found: " + scriptpath) 
    		return -1
    
    	return res # 0 = success
a month later

If you are having problems, make sure the 7zr you are addressing is the actual program (about 830-850 kilobytes) and not some sort of link (mine was about 40 bytes). I kept getting the return code 127 until I figured that one out...

2 years later