BASH: If condition uses result from find command to determine which file will be written - bash

I want to list all files in a nested directory, but in that directory has some files which having space in their name. So I wanna write down the paths of which files don't have space in their name and which have in 2 different files.
So far, I just know how to find those having space in their name by this command:
find /<my directory> -type f -name * *
I want something like:
find /<my directory> -type f
if [ name has space]
then > a.txt
else > b.txt
fi
Thank you in advance.

You can put a condition in a brief -exec. This is somewhat more complex than you would hope because -exec cannot directly contain shell builtins.
find "$path" -type f -exec sh -c 'for f; do
case $f in *\ *) dest=a;; *) dest=b;; esac;
echo "$f" >>$dest.txt
done' _ {} +
In other words, pass the found files to the following sh -c ... script. (The underscore is to populate $0 with something inside the subshell.)
If the directory tree isn't too deep, perhaps it would be a lot easier to just run find twice.
find "$path" -type f -name '* *' >a.txt
find "$path" -type f \! -name '* *' >b.txt

Use two separate commands:
find "$path" -type f -name '* *' > a.txt
find "$path" -type f -not -name '* *' > b.txt

Related

Rename file if it is the only one with the extension in directory

This works however I would like to do it only if it is the only .jpg for the given directory, the one below will just rename them all to folder.jpg, overwriting the other files:
find . -type f -name '*.jpg' -execdir mv {} 'folder.jpg' \;
I guess find cannot filter by the number of matches, but you can always exec a shell which does more elaborate checks for you:
find . -type f -name '*.jpg' -execdir sh -c '[ $# = 1 ] && mv "$1" folder.jpg' sh {} +

How to check all specific file type files are copied into a directory?

I've tried to compare specific file type (like .txt) and a specific directory by using the diff function but it doesn't turn out right. Can I get some help here?
backup=$(find . -name "*.text" -type f)
backup2=$(find /home/user/Desktop/backupfile -name "*.text" -type f)
diff -rq $backup $backup2
You can try the below, using a for loop comparing the files in both locations (if found) :
for f in ($find . -type f -name "*.text")
do
name=$(basename "$f")
if [ -f /home/user/Desktop/backupfile/"$name" ]
then
diff -rq "$f" /home/user/Desktop/backupfile/"$name"
else
echo match of "$f" not found under /home/user/Desktop/backupfile/
done

Count filenumber in directory with blank in its name

If you want a breakdown of how many files are in each dir under your current dir:
for i in $(find . -maxdepth 1 -type d) ; do
echo -n $i": " ;
(find $i -type f | wc -l) ;
done
It does not work when the directory name has a blank in the name. Can anyone here tell me how I must edite this shell script so that such directory names also accepted for counting its file contents?
Thanks
Your code suffers from a common issue described in http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29.
In your case you could do this instead:
for i in */; do
echo -n "${i%/}: "
find "$i" -type f | wc -l
done
This will work with all types of file names:
find . -maxdepth 1 -type d -exec sh -c 'printf "%s: %i\n" "$1" "$(find "$1" -type f | wc -l)"' Counter {} \;
How it works
find . -maxdepth 1 -type d
This finds the directories just as you were doing
-exec sh -c 'printf "%s: %i\n" "$1" "$(find "$1" -type f | wc -l)"' Counter {} \;
This feeds each directory name to a shell script which counts the files, similarly to what you were doing.
There are some tricks here: Counter {} are passed as arguments to the shell script. Counter becomes $0 (which is only used if the shell script generates an error. find replaces {} with the name of a directory it found and this will be available to the shell script as $1. This is done is a way that is safe for all types of file names.
Note that, wherever $1 is used in the script, it is inside double-quotes. This protects it for word splitting or other unwanted shell expansions.
I found the solution what I have to consider:
Consider_this
#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for i in $(find . -maxdepth 1 -type d); do
echo -n " $i: ";
(find $i -type f | wc -l) ;
done
IFS=$SAVEIFS

find: How to use found paths in the -exec directive?

I have a dozen files named
~/DOMAIN1.de/bin/dbdeploy.php
~/DOMAIN2.de/bin/dbdeploy.php
~/DOMAIN3.de/bin/dbdeploy.php
I want to run them all with the same arguments.
My bash script reads:
cd ~
find . -maxdepth 1 -type d -name "*\.de" -exec php56 bin/dbdeploy.php "$1" "$2" \;
However, the path given to exec seems not to be relative to the found subdirectory but rather to my PWD:
$ bash -x ./.dbpush "some argument"
+ cd ~
+ find . -maxdepth 1 -type d -name '*\.de' -exec php56 bin/dbdeploy.php 'some argument' ';'
Could not open input file: bin/dbdeploy.php
Could not open input file: bin/dbdeploy.php
Could not open input file: bin/dbdeploy.php
How can I use the found path in the -exec directive?
Ok, actually I found the answer myself:
The "find"-results are stored in {}, so the line reads
find . -maxdepth 1 -type d -name "*\.de" -exec php56 {}/bin/dbdeploy.php "$1" "$2" \;
Alternativly
find . -type f -wholename "*\.de/bin/dbdeploy.php" -exec php56 {} "$1" "$2" \;

Bash: execute a command on all files with extension recursively

I'm trying to use the following command:
herbalizer file_name.haml > file_name.erb
Here the file_name.haml is the file name, obviously.
How can I apply this command to all haml files in current directory recursively to all sub-directories? Filename should stay the same as mentioned above, so applying on abc.haml would be herbalizer abc.haml > abc.erb
So far: find . -type f -exec herbalizer {} \;
You're pretty close. You can use basename to strip the extension of the name of each file you find:
find . -type f -name \*.haml -exec sh -c 'herbalizer "{}" > "$(dirname {})/$(basename {} .haml).erb"' \;
I wrapped the i/o redirection in a shell command line. Filenames are enclosed in quotes in case a filename or path component contains spaces.
PS. That got you the job done, but it wasn't very elegant; so here's an alternative that uses bash's built-in substitution:
find . -type f -name \*.haml -exec bash -c 'FN="{}"; herbalizer "{}" > "${FN%.haml}.erb"' \;
You can use basename, dirname and find to get your desired results:
find . -type f -name "*.haml" | while read fname
> do
> herbalizer ${fname} > $(dirname $fname)/$(basename $fname .haml).erb
> done
Another simple method as suggested in the comments sections by #Dummy00001 is:
find . -type f -name "*.haml" | while read fname
> do
> herbalizer ${fname} > ${fname%.haml}.erb
> done
Further reference: Parameter substitution

Resources