How to excecute commands inside subdirectories of current directory in tcsh - tcsh

I am new to shell programming and using tcsh, i want to do the following.
i. Find out the subdirectories in the current directory(assume only subdirectories are present, nothing else, so that 'ls' is sufficient)
ii. Go into each of them one after another, and inside a folder named "abc", run a command present in a file command_file
Is the below valid. I'm confused about the syntax also:
set sub_TBs = `ls | awk '{split($0,a,":")'`;
foreach i (a) {
cd ./a[i]/abc
./command_file;}
Please help...

foreach dir (`find * -type d -maxdepth 0`)
cd $dir/abc
./command_file
cd ../..
end
Naturally, that's only if command_file is executable. If not, then replace that line with source command_file.

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*)

Trying to iterate through all files in local directory without the "." and ".."

Trying to write a bash script to process a bunch of sub-directories in the directory that its run in. I need to cd into each directory, compile some code, and run the executable. The problem is that when I iterate through the files in my current directory it includes the "." and ".." and I don't want those to be iterated on. What's the easiest way around this?
Current code I'm working with:
for file in .* *
do
echo "entering $file"
cd $file
done
Output looks like:
entering .
entering ..
By the time it looks for other files in my local directory its up too many directories to be useful. How do I remove . and .. from the list that I iterate through?
Apologies if this is a dumb question - very new to bash scripting.
Thanks in advance.
shopt -s dotglob will make * include dotfiles but not . and ...
3.5.8 Filename Expansion

Script location execution

I've been working on a script but always with a fixed directory (/opt/mw/script).
I need to change that to be able to execute the script from any directory.
I think I will need to add a "." at the beginning of the line to be able to execute the script?
For example ./mw/script
Is this correct?
Thanks
You already can execute that script from any directory with that absolute file path. It's the relative file paths (that start with ./ or ../) that can only be executed from a specific directory.
You need to add the "." if the script is in the current directory (e.g. ./script), but it is optional if the script is already inside another directory (e.g. mw/script).
Also notice that if your script contains relative references to other files and directories, you may need to use this trick to properly refer to them from any directory.
For instance, consider the following script using absolute paths:
#!/bin/bash
# lists all files in this directory
ls /opt/mw
If it is converted to relative paths as follows:
#!/bin/bash
# lists all files in this directory
ls mw
Then this script will only work if you run it from its own directory (e.g. cd /opt/ && ./script).
But then you can generalize it like this:
#!/bin/bash
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# lists all files in this directory
ls $SCRIPT_DIR/mw
Now the script works even when executed from another directory.

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 list all directories in present working directory?

I am new to shell scripting and wanted to list only the directories present in my present working directory.
To do this I found out the following way:-
ls -d */
Based on my understanding , this command will search for entities in pwd` that ends with "/" , but there is nothing in my directory that ends with "/", So, how does this expression works?
Also when I do simply do
ls -d
why does it simple show a ". " on the terminal
*/ is shell glob pattern that only matches directories in the current directory.
You can even get similar output using:
echo */
ls -d just formats it differently.
As per man ls:
-d Directories are listed as plain files (not searched recursively).
. means current directory
try:
ls -ld
output would show you the detail in current directory
Also we have pwd command to show the current working directory...
when you run ls -d it is run from the current working directory which is accessible from pwd command
At the end of the directory / is optional...
but when you are using global path for example ls /root... it is necessary to use / at first

Resources