Using Ghostscript in Automator? - macos

I'm a bit of a noob in automator, I hope this isn't a silly question.
I have a shell script compdf.sh that takes a pdf as input, flattens and compresses it, and saves it as a new file in the same directory with the suffix '_comp.pdf':
#!/bin/sh
OIFS=$IFS
IFS=‘.’
arr=($1)
prefix=${arr[0]}
suffix='_comp.pdf'
fout=$prefix$suffix
echo "Compressed file to be saved as $fout"
IFS=$OIFS
/usr/local/bin/gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dPDFSETTINGS=/ebook \
-sOutputFile="$fout" "$1"
This script works like a charm in terminal, by issuing the command compdf.sh <input_file>. I want to turn it into a service using automator, but when run it issues an error (simply says "action failed" in the "Run Shell Script" box:
(*Note: I've added "Get Specified Finder Items" so I can see the results in Automator.) Clearly I'm not passing the input to the script properly, yet this page says inputs are passed as $1-$n. Help?

The script requires that you specify the input --> "$#"
/usr/local/bin/compdf.sh "$#"

Related

Variable for a right-clicked item (say, a jpg) in a bash script?

I have a very simple bash script that I run often from the cli, but I've found it's frustrating to have to open a terminal, identify the right file, and run it and think the easiest way would be to run it as an option from a right-click. I am running Ubuntu 18.04 LTS.
The script is just erasing exif data, leaving the orientation tags, essentially this:
exiftool -all= -tagsfromfile # -Orientation file-*.jpg
Is there a way to have the script identify which image I'm right clicking on? I'm at a loss what to put in the file-*.jpg part which will be a variable for "whatever image I'm right-clicking on right now."
Tried searching for a good while on how to do this but am clearly either not using the right search terms or else this isn't done very often. Thank you in advance for any help!
if you want your script to run in file manager right-click menu you have to change your script and define file(s) as arguments. this happens simply by changing your file section with $1 to $n as the parameter(s).
as far as I know ubuntu uses nautilus as an file manager.
you can run nautilus-actions-config-tool either from your terminal or from dash and define your script a name and a command to run. you can follow this link for illustration learning :
ubuntu nautilus defile script in menu
for example :
#!/bin/bash
if [ "$1" != "" ]; then
echo "Positional parameter 1 contains value $1"
else
echo "Positional parameter 1 is empty"
fi
for all arguments :
#!/bin/bash
if [[ "$#" -gt 0 ]]; then
for arg in "$#"; do
echo $arg
done
fi
here is the image that shows the script worked
I know the question is a little older, but I can provide you with the solution.
You have to set up FileManager-actions, an extension for GNOME/Nautilus (but it also works for other file managers).
Setup filemanager-actions on Ubuntu 20.04
sudo apt update
sudo apt install filemanager-actions
Then run fma-config-tool and create a new action.
When creating an action, please ensure that:
[v] Display item in selection context menu
is flagged; otherwise, you will not see the context menu during the file selection.
Prepare the script you want to execute
Prepare a script that does what you need. Touch in /tmp, mv it in /usr/bin and give it execute permissions:
touch /tmp/your-script
# edit it with your editor
sudo mv /tmp/your-script /usr/bin/
sudo chmod +x /usr/bin/your-script
In your script, you can reference the filename using $1.
FILENAME=$1
echo $FILENAME
In the variable FILENAME you will find the selected file name.
Configure Nautilus-action command
To let nautilus pass the filename, insert the script path and the argument string in the' command' tab.
To fully answer your question, to let Nautilus pass the filename as a script argument, you have to specify %f.
At this point, quit the Nautilus instance and open it again:
nautilus -q
nautilus
Now, let's have a try! Right-click on a file and check out the result!
Appendix 1 - Filemanager-actions formats
%f A single file name, even if multiple files are selected.
%F A list of files. Each file is passed as a separate argument to the executable program.
%u A single URL. Local files may either be passed as file: URLs or as file path.
%U A list of URLs. Each URL is passed as a separate argument to the executable program.
%d Base directory
Here you can find a comprehensive list.
Appendix 2 - Sources
Check out my post blog in which I actually realize something similar: https://gabrieleserra.ml/blog/2021-08-14-filemanager-actions-ubuntu-20-04.html
Reference to all possible formats for FileManager-actions: https://askubuntu.com/a/783313/940068
Realize it in Ubuntu 18.04: https://askubuntu.com/a/77285/940068

.sh output to .txt file - what am I doing wrong?

I am running Windows 10 and am trying to save the error output of a test.sh file to a text file.
So I created the test.sh file and wrote an unkown command in it (i.e. "blablubb").
After that I open the terminal (cmd.exe), switch to the directory and type test.sh 2>> log.txt.
Another window opens with "/usr/bin/bash --login -i \test.sh" in the title bar, shows me "bash: blablubb: command not found" and then closes immediately.
I want to save that output because the bash-window just opens for a split second. Every google search brings me to websites talking about redirecting the output and that Stream2 ist STDERR and therefore I should use test.sh 2>> log.txt or something smiliar that takes care of the STDERR stream.
If I try the same with a test.sh file and the content:
#!/bin/bash
echo hi there
I get the output in the briefly open bash-window:
bash: #!/bin/bash: No such file or directory
hi there
But the log.txt file is empty.
If I only have echo hi therein the test.sh file I get bash: echo: command not found in the bash-window.
The log.txt also empty.
If I type the following directly in the terminal, the output is written in the log.txt:
echo hi > log.txt 2>&1
If I type directly in the terminal:
echdo hi > log.txt 2>&1
I get 'Der Befehl "echdo" ist entweder falsch geschrieben oder konnte nicht gefunden werden.' in the log.txt file.
So I guess the redirecting of the output works fine until I use test.sh.
I know that .sh files are something from the unix world and that the problem might lie there but I don't know why I can not redirect the output briefly shown in the bash-console to a text file.
The 2>> redirection syntax only works if the command line containing that syntax is interpreted by bash. So it won't work from the Windows command prompt, even if the program you are running happens to be written in bash. By the time bash is running, it's too late; it gets the arguments as they were interpreted by CMD or whatever your Windows command interpreter is. (In this case, I'm guessing that means the shell script will find it has a command line argument [$1] with the value "2".)
If you open up a bash window (or just type bash in the command one) and then type the test.sh 2>>log.txt command line in that shell, it will put the error message in the file as you expect.
I think you could also do it in one step by typing bash -c "test.sh 2>>log.txt" at the Windows command prompt, but I'm not sure; Windows quoting is different than *nix quoting, and that may wind up passing literal quotation marks to bash, which won't work.
Note that CMD does have the 2>> syntax as well, and if you try to run a nonexistent windows command with 2>>errlog.txt, the "is not recognized" error message goes to the file. I think the problem comes from the fact that CMD and bash disagree on what "standard error" means, so redirecting the error output from Windows doesn't catch the error output by bash. But that's just speculation; I don't have a bash-on-Windows setup handy to test.
It would help to know if you are running Windows Subsystem for Linux (Beta). Or if you are doing something else. I'm assuming this is what you are doing on windows 10.
If this is the case are you using bash to run the script?
Are you using win-bash?
If it is win-bash I'm not very familiar and would recommend Windows Subsystem for Linux (Beta) for reasons like this. win-bash, while cool, might not be compatible with redirection operators like 2>>.
You have stdout and stderr, by default (if you don't specify) the >> (or append) will only append standard output into the txt file.
If you use 2 it will append the standard error into the txt file. Example: test.sh 2>> log.txt
This could be better described at this site.
To get exactly the command for append both stdout and stderr, go to this page.
Please tell me if this doesn't answer your question. Also, it could be more valuable to attempt a search for this answer first and explain why your search found nothing or give more extensive clarification as to what the problem is. I love answering questions and helping, but creating a new forum page for what might be an easy answer may be ineffective. I've had a bunch of fun with your question. I hope that I've helped.
That's makes a lot of sense. Thanks Mark!
Taking what mark says into account I would get Windows Subsystem for Linux (Beta). There are instructions here. Then run your script from there.

Copying .jpg file using shell script gives 'Failed to open input stream for file' error

Very simple script to copy a file
#!/bin/bash
#copy file
mtp-getfile "6" test2.jpg
I set it as executable and run it using
sudo sh ./test.sh
It gives me a file called test2.jpg that has no icon and I cannot open I get a 'Failed to open input stream for file' error
However, if I simply issue the following from the command line
mtp-getfile "6" test2.jpg
It works as expected. What is wrong with my script? I checked and the resulting .jpg file in each case has the same number of bytes. Very strange.
As commented by chepner, your file might have a DOS (Windows) invisible line ending on its name, which would cause an error. To get rid of this unwanted character(s), just create a new blank script on your "nix" system and type the name by hand (not by copying and pasting, to avoid problems), let's say, name it test2.sh.
Then copy all the contents of test.sh to test2.sh (copy and paste) and run test2.sh and see if it works. If it doesn't, try running the following code on the new script, to make sure that there are no unwanted characters on the code itself:
tr -d "\r" < /folder/test2.sh && echo >> /folder/test2.sh
And then try to run script2.sh again to see if it works. Note: the echo >> /folder/test2.sh part of the code above is just to make sure that your new script ends with a newline, which is a Posix standard (and without which some programs may misbehave because they expect the file to end with a newline).
Apparently it was a permissions issue.
I only had to do a sudu chown test2.jpg

Execute a shell command on a file selected in the Finder

I'm a very novice and infrequent applescript experimenter. I've tried for several hours now to learn the individual applescript commands for the following task, but I always run into errors. Perhaps someone much more adept at applescript will find this task easy and quick, and for that I would be very grateful. Here is the task:
I want to be able to manually select a document or file within the finder and then execute the following unix command on that file. I would then store the script under Finder's "Services" menu. The unix command is:
srm -rfv -m path/filename
In my attempts, I assumed that a script that would open Terminal and execute the command would be the way to go, but just couldn't get anything to work. Thank you in advance to any good programmers who can whip out such a script for me.
My tip: Create such services using Automator!
Create a new Service in Automator
Choose "File & Folder" as Input and "Finder"
Add "Run shell script"
Choose "as arguments" as input
Change echo "$f" to your command srm -rfv -m "$f"
Save it as "Safe delete"
From now on, if you select a file inside Finder you will find the option "Safe delete" in the context menu.
Enjoy, Michael / Hamburg
Craig's comment is pertinent, but I am just focus on the script itself, not on the shell command. the script bellow must be saved as Application and each time you drop 1 or more file on its icon, the shell script command will be executed for each file :
on open myFiles
repeat with aFile in myFiles -- repeat loop in case you drop more than 1 file on the icon script
try
do shell script "srm -rfv -m " & (quoted form of POSIX path of aFile)
end try
end repeat
end open
Still make sure that in your shell command 'srm -rfv', the 'v' is necessary because this script will not display any thing ! I don't think so. also I did not display error during remove. what do you want to do with error (like write protect, ...) ?
Update: I missed that the OP wants to create an OS X Service that integrates with Finder. ShooTerKo's answer shows how to do that (and his solution doesn't even require use of AppleScript).
The only potentially interesting thing about this answer is that it demonstrates AppleScript commands to open a file-selection dialog, get the chosen file's POSIX path and run a shell command with it, with some general background information about executing shell commands with do shell script.
Try the following:
# Let the user choose a file via an interactive dialog.
set fileChosen to choose file
# Get the file's POSIX path.
set filePath to POSIX path of fileChosen
# Use the path to synthesize a shell command and execute it.
do shell script "echo srm -rfv -m " & quoted form of filePath
Note:
There's no explicit error handling; if you don't want the script to just fail, you'll have to add error handling (try ... on error ... end try) to handle the case of the user canceling the file selection and the shell command failing (unlikely in this case).
The shell command has echo prepended to it in order to perform a dry run (see its output in Script Editor's Result pane); remove it to perform the actual deletion.
quoted form of is important for ensuring that a string value is included as-is in a shell command (no risk of expansion (interpretation) by the shell).
do shell script will NOT open a Terminal window - it will simply run the shell command hidden and return its stdout output, which is usually what you want. If the shell command signals failure via a non-zero exit code, an error is raised.

KDE: klipper action script

So KDE's clipboard manager - klipper - allows one to write a script to be applied to clipboard contents matching regexp. Say, I want klipper to download an image through bash script.
Here's a klipper QRegExp:
^http://.*\.(png|svg|gif|jpg|jpeg)
I know that this regexp works - klipper notifies me every time I copy image URL to clipboard. Then, here's a bash script
#!/bin/bash
# let's name it clip.bash
name=`basename $1`
curl -o ~/Downloads/$name $1
I put this script to the PATH (I tried to feed this script with a image URL my self - it works), and finally I specify an action the following way:
clip.bash \%s
everything's fine and taken care about - but it doesn't work!
So my question is: "how to make klipper download an image through the bash script?"
First thoughts:
Are you sure about the backslash before the '%'? I haven't access to KDE right now, but I'm not sure you need it.
Are you sure that klipper "sees" your change to the PATH variable? You could try to use absolute path (something like "/home/../clip.bash")
If those don't work, you can try to log some debug info from your script. For example:
#!/bin/bash
name=`basename $1`
echo "curl -o ~/Downloads/$name $1" 1>&2
Run
tail ~/.xsession-errors
to see what command your script have just tried to execute.

Resources