New answers tagged find
2
Just use ! -type d:
find . -type d \( -path ./.git -o \
-path ./log -o \
-path ./public -o \
-path ./tmp \) -prune -o \
! -type d -print
-1
Here's one way to do it. I'm piping your output from find (using xargs) to a little bit of bash which asks the question "Is this not a directory?" and if it's not, it echoes it to your terminal.
Here's the whole she-bang:
find . -type d \( -path ./.git -o -path ./log -o -path ./public -o -path ./tmp \) -prune -o -print | xargs -i bash -c 'if [ ! -d "{}" ]; ...
1
find . -type f
will do it. You can do exec if you want to operate on file names.
2
You can't really influence environment "horizontally" in the pipe - the processes in a ... p_n | p_n+1 | p_n+2 ... pipe are spawned by the same shell interpreter, hence there is no way to change environment variable of say p_n from p_m, echii is in the same pipeline.
If you just need to do a simple transformation of the filenames, which can be achieved with ...
2
You don't need pipes for that the find command in itself is capable of doing that:
find . -name "*.dat" -exec mv -t . {} \;
Notice that this is somewhat inefficient as the .dat files already in the current directory are found and moved as well.
2
You can use the basename program to get the file name:
find . -type f -name \*.c -exec basename {} +
This works on finds that don't have the GNU -printf extension.
4
Using awk is not so complicated:
find . -name '*.c' -type f | awk -F/ '{print $NF}'
Or sed:
find . -name '*.c' -type f | sed 's|.*/||'
(assuming file names don't contain newline characters) and that will work with any find implementation.
1
GNU find knows -printf. If you search subdirectories, too, then file names can occur multiple times (in general)!
You need -printf "%p\n" or -printf "%f\n".
5
GNU find supports the -printf predicate, which supports the %f format specifier for outputting on the filename.
find -type f -name "*.c" -printf '%f\n'
4
What is the purpose of having these two operators then?
That's an easy one: Because there are different use cases. Sometimes it is useful to truncate the target file to size 0 first, sometimes (e.g. log files) it makes more sense to append data to a file.
In this case it makes no sense to append. You want a file with exactly the content of the files ...
8
The second example:
find . -name *.txt -print0 | xargs -0 cat > out.txt
Is completely legal and will recreate the file, out.txt each time it's run, while the first will concatenate to out.txt if it runs. But both commands are doing essentially the same thing.
What's confusing the issue is the xargs -0 cat. People think that the redirect to out.txt is ...
1
I would go with the second one. The redirect of stdout gets caught by bash when you hit enter, so it's not like you create a new redirect for every line of find/xargs (which might have been their thinking). If out.txt doesn't exist they should be identical, if it already has data, then the second one at least resets the file to known content (that is, no ...
2
chmod -R o-w .
Will remove write permissions to others for every file in a safe way. It will however update the ctime of every file including the ones for which others already didn't have write access.
With GNU chmod, you can make it show which files needed updated with the -c option:
$ chmod -cR o-w .
mode of `./a' changed from 0777 (rwxrwxrwx) to 0775 ...
1
Your approach is a performance nightmare: You create two processes for every file! One completely uselessly because find already has this information and can easily print it. This is a better solution:
find . -perm -o=rwx -printf "%m %p_\0" 2>/dev/null |
while read -r -d '' perms path; do
path="${path%_}"
echo "${perms} '${path}'" >&2
...
1
/007 will show your only files that have no permissions for owner and group, and all permissiosn (rwx) for other.
You might have more luck with /o=rwx. That will match only the other permissions for the file.
EDIT FOR CORRECTNESS:
Apparently, you'll need to use -perm -o=rwx, because the /o is an inclusive filter, and would match files where other has ...
2
I am not sure what you want to do with the files after you find them, but for interactive use in zsh I would use something like this:
ls **/trunk/**/config/*.xml
6
That's not a regex. For globs one should use the -path predicate instead.
1
find -L . \
\( -type d \
\( -path "*/ignore" -o -path "*/indeed" -o \
\( -path "*/subdir/*" ! -path "*/subdir/save" \
\) \
\) \
\) \
-prune -o -print
If you want extra filter (like -name "*.ext") you have to put that right before -print. The last part then looks like this
-prune -o \( -name "*.ext" \) -print
Note that I ...
1
Here is a portable and efficient way to execute multiple commands with find without using the GNU specific "-print0" and "xargs -0" tricks :
find . -name "*.haml" -exec sh -c 'for i; do echo $i;ls -l $i;haml --check $i; done' sh {} +
4
Also a way without xargs:
find . -name "*.haml" -ls -exec haml --check {} \;
to print out only file name with path:
find . -name "*.haml" -print -exec haml --check {} \;
2
find . -name "*.haml" -print0 | xargs -0 -n 1 --no-run-if-empty haml --check
runs haml on each file found by find
If haml can take multiple files in one invocation, you can leave out the -n 1
2
You're deleting the \;. Just do this:
find . -type f -exec grep -il "search string" {} \; > log.txt
0
You have to prevent that */base itself is matched:
Edit 1:
find -L . -type d \
\( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \
\( -wholename "*/base/*" -a \
\( ! -wholename "*/base/subdir" -a ! -wholename "*/base/subdir/*" \) \) -o \
\( -wholename "*/base/subdir/*" -a \
\( ! -wholename "*/base/subdir/requiredPath" -a ! ...
0
foo ()
{
local subdirs=() target="$1" dest="$2";
while IFS= read -rd ''; do
subdirs+=("$REPLY");
done < <(find "$target" -type f -iname '*.avi' -exec bash -c 'printf "%s\0" "${@%/*}"' _ {} + | sort -zu);
cp -rp -- "${subdirs[@]}" "$dest"
}
Usage: foo <source directory> <destination directory>
Which will also ...
2
First, why your attempt doesn't work: -printf "%h\n" prints the directory part of the .avi file name. That doesn't affect anything in the subsequent -exec action — {} doesn't mean “whatever the last printf command printed”, it means “the path to the found file”.
If you want to use the directory part of the file name in that cp command, you need to modify ...
1
Since you seem to be using GNU tools, you could do:
find . -name '*.avi' -printf '%h\0' |
tr '\1/' '/\1' |
LC_ALL=C sort -zu |
tr '\1/' '/\1' |
awk -vRS='\0' -vORS='\0' '
NR>1 && substr($0, 1, length(l)) == l {next}
{print; l=$0"/"}' |
xargs -r0 cp -rt /share/USBDisk1/Movies/
The above is GNU specific:
for find (because of ...
-2
The spaces in the values can be avoided by as simple for loop construct
for CHECK_STR in `ls -l /root/somedir`
do
echo "CHECKSTR $CHECK_STR"
done
ls -l root/somedir contains
my file with spaces
Output of above
my
file
with
spaces
to avoid this output, simple solution (notice the double quotes)
for CHECK_STR in "`ls -l /root/somedir`"
do
echo ...
-2
You can use xargs and cp to make the work:
find . -name "*.avi" -printf "%h\n" | xargs cp -t /share/USBDisk1/Movies/ -r
0
There is an slight inaccuracy into slm answer.
NOTE & Disclamer : this have to be a comment to slm answer but righ now I can't do comments yet.
The example "someone has maliciously created a link " given into Additional considerations around security is not totally accurate both about Unix hard links and for Unix soft links.
To understand the ...
7
Just swap \0 and \n:
find ... -print0 |
tr '\0\n' '\n\0' |
head |
tr '\0\n' '\n\0'
Note that some head implementations can't cope with NUL characters (and they're not required to by POSIX), but where find supports -print0, head and text utilities generally support NUL characters.
You can also use a function to wrap any command between the two trs:
...
0
This is a good use for env [command]
env verify
Is one way to invoke a command when you do not know where it is.
BTW: /bin is a symlink on a lot of systems , Solaris for example.
4
Gah.
[jake@jace]/bin% ls -lhd /bin
lrwxrwxrwx. 1 root root 7 May 22 2012 /bin -> usr/bin/
I'm running Fedora 17. Apparently /bin is symlinked to /usr/bin. And of course (and quite rightly) find and locate ignore symlinked directories to avoid result pollution.
0
find -L . -type l |xargs symlinks will give you info whether the link exists or not on a per foundfile basis.
1
With GNU find (i.e. under non-embedded Linux or Cygwin), you can use -regex to combine all these -path wildcards into a single regex.
find . -regextype posix-extended \
-type d -regex '\./(\..*|Music|Documents)' -prune -o \
-type f -regex '.*(\.(bck|bak|backup)|~)' -print0 |
xargs -0 --no-run-if-empty trash-put
With FreeBSD or OSX, use -E ...
7
That would happen if /var/lib/tomcat7/conf is a symbolic link to /etc/tomcat7.
By default, find (the coreutils version anyway) will not follow symlinks. Try with the -L flag:
find -L / -name "server.xml" -print
1
As far as I know, there is no option to tell find to read patterns from a file. An easy workaround is to save the patterns I want to exclude in a file and pass that file as input for a reverse grep. As an example, I have created the following files and directories:
$ tree -a
.
├── a
├── .aa
├── .aa.bak
├── a.bck
├── b
├── .dir1
│ └── bb1.bak
├── dir2
│ ...
0
This seems to be more a shell question than a find question. With a file containing ( -name dir1 -o -name dir2 ) -prune (no "\"!) you can simply do this:
find ... $(< /path/to/file)
Without changing the find call itself (to eval find or by changing $IFS) this works with paths without whitespace only, though.
If you want to keep the file simpler you ...
4
Look at the error output: you should be seeing find: `…' Permission denied errors. The first thing you do is remove all access permissions from $topdir, which prevents recursing further into it. None of the chmod commands you expect are executed except for the very first one.
If you want to remove the permission to access all the directories in a tree, you ...
0
Maybe my answer will helpfull for someone:
#!/bin/bash
findpath=$(echo $1 | sed -r 's|(.*[^/]$)|\1/|')
# tarballs to check in
find $findpath -type f | while read tarball; do
# get list of files in tarball (not dirs ending in /):
if [ -n "$(file --mime-type $tarball | grep -e "application/jar")" ]; then
jar tf $tarball | grep -v '/$' | ...
Top 50 recent answers are included



