Execute command from another directory without really moving - shell

Consider this directory structure
/dir1/Quack.sh
/dir2/ <- We are here
Is it possible to execute Quack.sh as if I were currently in /dir1/ without actually cd'ing there?
The main reason I'm asking is because Bundle is complaining when running executables who depends on it when the executable is ran from outside the folder. The executable runs fine if executed from the directory it is contained in.

You can create sub-shell and do cd, script execution:
(cd ../dir1/; ./Quack.sh)
OR else use find -execdir
find ../dir2/ -maxdepth1 -name "Quack.sh" -execdir '{}' \;

Related

Find and execute command on all files in directory that have a specific folder name

I want to use the find command to execute a special command on all of the files inside the directory that are contained inside multiple different directories with a specific keyword in it (the keyword is "Alpha") and keep the output inside the working directory of the initial file I ran the command on.
The command works such that it requires to you to provide the initial file to perform the command on and then the name of the newly converted file. So like this
command file_to_run_command_on.txt new_file.txt
This is my code
find $PWD -name *.txt* -exec command {} new_file. \;
Right now, it finds all the text files in this directory even in the sub directories and outputs just one file in the directory I run the initial find command from. I'm also unsure how to add the additional search for the keyword in the directory. All advice appreciated!
-exec runs the command in the directory from which you start find.
-execdir runs the command in the matching file's directory.
To only find *.txt* files whose parents contain a specific file, you could use:
find "$PWD" -path "*keyword*/*.txt*" -execdir command {} new_file \;
This will run the command for foo/bar/some-keyword-dir/baz/etc/file.txts but not for foo/bar/baz/file.txts (no keyword in parent directory names) or foo/bar/some-keyword-dir/baz/file.tar (not *.txt*)

Moving files older than 1 hour from one directory to another - AIX

I am trying to move files older than one hour, which are being populated almost every minute very rapidly to another folder whose name specifies the particular hour, in aix.
The script i was trying to run is:
find /log/traces/ -type f -mmin +59 -exec mv '{}' /Directory \;
The above script gives me an error:
find: bad starting directory
I am a newbie to shell scripting.
Any help will be highly appreciated.
------------------Edited-----------------------
I have been able to move the files older than 1 hour, but if the specified folder does not exist, it creates a file with the name specified in command and dumps all the files in it. The script i am running now is:
find /log/traces -type f -mmin +59 -exec mv '{}' /Directory/ABC-$(date +%Y%m%d_%H) \;
It creates a file named ABC-[Current hour]. I want to create a directory and move all the files into it.
If you are not running as a root user you may be getting this problem because of read permissions on /log/traces/.
To see the permission level of this directory run ls -l /log/traces/ the left most column will display something like this drwxr-xr-x which is an explanation of what permission settings that directory has. To understand more read this.
You need to ensure the user you are executing your command as has read access to /log/traces/ - that should fix your error.
Does the directory /Directory- (Timestamp) exist before the script exist? I am guessing the directory is not there to move the files. Make sure the directory exists before you start moving.
You can create a shell script for moving the files that will take the target directory as a parameter along with the file name. Tf the target directory does not exist the script creates the directory. After that script will execute mv command to move the file to the target directory.
Don't bother moving the files, just create them in the right folder directly. How?
Let crontab run each hour and create a dir /Directory/ABC-$(date +%Y%m%d_%H).
And now make a symbolic link between /log/traces and the new directory.
When the link /log/traces already exists, you must replace the link (and not make a link in a subdir).
newdir="/Directory/ABC-$(date +%Y%m%d_%H)"
mkdir -p "${newdir}"
ln -snf "${newdir} /log/traces
The first time you will need to mv /log/traces /log/traces_old and make the first link during a small moment that no new files are created.
Please test first with /log/testtraces first, checking the correct rights for the crontab user.

Can not figure out how to run a file stored in a variable found with 'find' in shell script in Terminal on OSX

The code I have at the moment is:
#!/bin/bash
cd "/Users/{User}/Documents/jarfiles/"
runnable_game=$(find . -type f -name 'game\..*\.jar')
echo $runnable_game
eval $runnable_game
in my Documents folder I have a folder jarfiles and within that folder there is only 1 jar file, although if possible only make it select the first file found.
The goal is to execute this file. for example: /Documents/jarfiles/game.1234.jar should be run.
for debug I put an echo in there, but the echo returned nothing, a blank line.
I have some programming skill, but I am not professional and in no way used to shell scripts or terminal command line magic. (I program in Java, C and such...)
Any idea to make a script that finds a file and runs it?
to clarify:
I don't know the filename in advance any .jar file to that format should be run, basically I download a file to that directory which is in that format
To execute a jar file you know is there but you don't know the exact name,
you can use a simple shell wildcard,
you don't need the find command:
java -jar game*.jar
If you want to execute only the first file found, then find can be indeed useful:
find . -name 'game*.jar' -exec java -jar {} \; -quit
Correct shell code to run 'game' + any string + 'jar'
#!/bin/bash
cd "/Users/{User}/Documents/jarfiles"
java -jar $(find . -name 'game.*jar')
game\..*\.jar escaping using \ seemed to not work
this will find files starting with game and ending with jar, not game. and .jar, which is not a problem (at the moment).

Is it not possible to use the CLI, bash in this case, to find a set, take a set, move it, and not have to write a library to do so

I thought this would be more of a one liner to be honest.
Pretty simple in notion:
using find on Mac OS X, locate files that meet a criteria, in my case:
all file and directories in a directory:
find ~/Downloads +time1000s
That finds what I need, then I run a conditional, if a dir exists, delete it, if not, create it:
mkdir -p ~/.Trash/safe-to-delte-these-old-files
This means I need to add print0 to my find as files will have spaces, and I want to move, not copy but either way, there is a source, and a destination, and I am getting stuck:
https://gist.github.com/5c0tt/5a2c1fd39ae99d6fca05
Line 27 and 26 seem to cause me issues, I am stuck.
Suggestions on everyone from line 1 to the end. I am trying to hard to do this with POSIX in mind, but i can't even get variables to work then.
It seems BSD does not work the exact same way as other shells and what arguments they accept, which is why I am trying to be more POSIX, as I was told it should run anywhere then.
Thank you.
Took a glance at your git link, a couple of remarks if I may (still a noob tbh so may be irrelevant) :
dir_to_clean="/Users/my_username/Downloads" should probably be dir_to_clean="/Users/$current_user/Downloads" unless you actually have a literal /Users/my_username/Downloads folder.
Instead of cd'ing into your users directory and since you have hardcoded the path to that directory, you could use pushd & popd instead in order to build a stack of directories.
To answer your question, to capture files with spaces in the name for removal you could use something like :
find $dir_to_clean -not -name . +time1000s -exec mv -- {} ~/.Trash/
Could be something like this :
# Initialise variables, user, source to clean, destination
user=$(whoami);
src="/Users/$user/Downloads";
dest="~/.Trash/safe_to_delete";
# Move to directory to clean, not necessary, but if you really want to
pushd $src;
# Check if the destination exists, if not, create it
if [ ! -d $dest ]; then
mkdir -p $dest;
else
echo "destination already exists";
fi
# Find all the file to move then move them
find . -not -name . +time1000s -exec mv -- {} "$dest/" \;
# Return to previous working directory
popd;
pushd the $src directory onto the stack. find all the files in the now current directory ., -not -name . in order to avoid trying to trash the . & .. folders, -- tells find to stop parsing command line options (in cas your file/folder is named i.e. -myfile.txt), exec mv all of the arguments to $dest. popd the still current directory off of the stack. man find (/exec) for more details.
Note : It is also interesting to know that the difference of execution time between the -exec option versus results being piped into xargs can and will often be quite dramatic. Also, if your are actually sure that those files are safe_to_delete, then delete them instead of moving them (-exec rm -- {} $dest/). With all that said, you were correct, one liner.
Further reading :
http://www.softpanorama.org/Tools/Find/using_exec_option_and_xargs_in_find.shtml

How to clean up directory structure from botched rsync operation?

In a bash script, I am rsync'ing many directories. However, in my script I forgot to put a trailing slash at the end of the source directory. As a result, I have something like
rsync /first/path/dir /second/path/dir
in my script, which I know is wrong, and ends up creating
/second/path/dir/dir
in the destination directory, which is not what I want at all.
Is there a quick way I can use the find command to find all instances of "dir/dir" and perform an 'rm -rf' without losing the other original contents of /second/path/dir ?
you can use the -path argument to unix find command to locate (and remove) 'dir/dir'
find . -path \*/dir/dir -exec rm -rf {} \;

Resources