Executing `make` inside multiple directories - shell

I am trying to run make command inside multiple folders which start with g-. How can I do so?
I was wondering if I could use "find" command to solve it. Can you help me to understand it better?
I tried:
find . -type d -name "g-*" -exec make {}\;

You need to invoke make with the -C option.
find . -type d -name 'g-*' -exec make -C {} \;

From your attempt, I conclude that each g- directory contains a suitable Makefile. Hence you can do a
find . -type d -name 'g-*' -exec sh -c 'cd {}; make' \;

Related

Find and rename files by pattern works in Debian, but not in CentOS7

I need to find and rename files with question mark in names.
Example: "style.css?ver=111" should become "style.css"
I use this command
find . -type f -name "*\?*" -exec rename 's/\?.*//' '{}' \;
In Debian all works fine, but in CentOS7 I get and error that "rename: not enough arguments
"
Any ideas why?
For a reliable option that should work in any POSIX-compliant system, you may use
find . -type f -name "*\?*" -exec sh -c 'mv -- "$1" "${1%%\?*}"' findshell {} \;
$1 is the name of each file found and ${1%%\?*} is a construct that strips the substring starting from the question mark.
That should be enough if you have a few matching files. If you need it, a more efficient alternative is
find . -type f -name "*\?*" -exec sh -c '
for file in "$#"; do
mv -- "$file" "${file%%\?*}"
done
' findshell {} +

execdir and rename commands together?

I ask a question about finding, copying and renaming which can be found here Find, copy, rename within the same directory
The answer was great and solved the issue I had in that thread but it did bring up another question about how I can rename just part of the file....for example when running this command;
find /home/ian/Desktop/TEST/ -type f -mmin -1 -execdir echo cp \{} \{}_backup \;
and the file is called TEST_MASTER how can you run the above and have the new file called TEST_BACKUP as opposed to TEST_MASTER_BACKUP?
I can solve this by running a new rename command straight after like below;
find /home/ian/Desktop/TEST/ -type f -mmin -1 -execdir cp \{} \{}_backup \; ;
rename __MASTER_backup _backup *MASTER_backup ;
but there must be a way to do this in one go?
All the best,
Ian
You can use this find command:
find /home/ian/Desktop/TEST/ -type f -mmin -1 -execdir bash -c 'cp "$1" "${1%%_*}_BACKUP"' - '{}' \;
I came with almost the same answer as anubhava:
find /home/ian/Desktop/TEST/ -type f -name '*_MASTER' -mmin -1 -execdir \
bash -c 'mv $1 ${1/MASTER/BACKUP}' - \{} \;
This will only backup *_MASTER files. If you need to backup the other files as well (and add an extra _BACKUP at the end, vote for anubhava!

How to add .txt to all files in a directory using terminal

I have many files without file extention. Now I want to add .txt to all files. I tried the following but it gives an error, mv: rename . to ..txt: Invalid argument.
How can I achieve this?
find . -iname "*.*" -exec bash -c 'mv "$0" "$0.txt"' {} \;
You're nearly there!
Just add -type f to only deal with files:
find . -type f -exec bash -c 'mv "$0" "$0.txt"' {} \;
If your mv handles the -n option, you might want to use it (that's the option to not overwrite existing files).
The error your having is because . is one of the first found by found, and your system complains (rightly) when you want to rename .! with the -type f you're sure this won't happen. Now if you wanted to act on everything inside your directory, you would, e.g., add -mindepth 1 at the beginning of the find command (as . is considered depth 0).
It is not very clear in your question, but what if you want to add the extension .txt to all files that don't have an extension? (we'll agree that to have an extension means to have a period in the name). In this case, you'll use the negation of -name '*.*' as follows:
find . -type f \! -name '*.*' -exec bash -c 'mv "$0" "$0.txt"' {} \;

Performance difference in find command

Is there any performance difference in the below shell commands:
find . -type f -empty -exec rm '{}' \;
find . -type f -empty -exec sh -c "/bin/rm {}" \;
Your 2nd command is going to be slower since it will spawn a sub shell for each entry found by find command.
However at the same time 2nd command will be more flexible in nature if you want to do some variable assignment etc like this:
find . -type f -empty -exec sh -c "x=1; /bin/rm {}" \;

bash: -exec in find command and &

I want to run:
./my_script.py a_file &
... on all files in the current folder that end with .my_format, so I do:
find . -type f -name "*.my_format" -exec ./my_script {} & \;
but it doesn't work. How should I include & in the -exec parameter?
Try this:
$ find . -type f -name "*.my_format" -exec sh -c './my_script {} &' \;
The mostly likely reason your attempt didn't work is because find executes the command using one of the exec(3) family of standard c library calls which don't understand job control - the & symbol. The shell does understand the "run this command in the background" hence the -exec sh ... invocation
Try this find command:
find . -type f -name "*.my_format" -exec bash -c './my_script "$1" &' - '{}' \;

Resources