find does not descend to some directories - bash

find . should, according to my knowledge print out recursively everything in the current directory, however when I use it in a directory I'm getting the following
.
./WORKSPACE
./bazel-out
./lib
./lib/BUILD
./lib/hello-time.h
./lib/hello-time.cc
./main
./main/BUILD
./main/hello-world.cc
./main/hello-greet.h
./main/hello-greet.cc
./bazel-stage3
./bazel-bin
./bazel-testlogs
./README.md
./bazel-genfiles
however, this is not everything -- at least the folder bazel-bin contains some files. Actually, if I run find bazel-bin, this is what I get:
bazel-bin/
bazel-bin/lib
bazel-bin/lib/_objs
bazel-bin/lib/_objs/hello-time
bazel-bin/lib/_objs/hello-time/hello-time.pic.d
bazel-bin/lib/_objs/hello-time/hello-time.pic.o
bazel-bin/lib/libhello-time.a
bazel-bin/lib/libhello-time.a-2.params
bazel-bin/main
bazel-bin/main/_objs
bazel-bin/main/_objs/hello-greet
bazel-bin/main/_objs/hello-greet/hello-greet.pic.o
bazel-bin/main/_objs/hello-greet/hello-greet.pic.d
bazel-bin/main/_objs/hello-world
bazel-bin/main/_objs/hello-world/hello-world.pic.o
bazel-bin/main/_objs/hello-world/hello-world.pic.d
bazel-bin/main/libhello-greet.so
bazel-bin/main/hello-world.runfiles_manifest
bazel-bin/main/libhello-greet.so-2.params
bazel-bin/main/hello-world-2.params
bazel-bin/main/libhello-greet.a-2.params
bazel-bin/main/hello-world.runfiles
bazel-bin/main/hello-world.runfiles/__main__
bazel-bin/main/hello-world.runfiles/__main__/main
bazel-bin/main/hello-world.runfiles/__main__/main/hello-world
bazel-bin/main/hello-world.runfiles/MANIFEST
bazel-bin/main/libhello-greet.a
bazel-bin/main/hello-world
Why the find . does not descend into bazel-bin?
Thank you.

My bet is that bezel-bin is a soft link within your current directory.
Find will not traverse the soft link. You should try find . -follow

Related

How to remove a file named '.'?

Ok so i did something very stupid (copying a file and renaming it '.') since I thought it would just copy it as .uniprot_sprot.fasta.gz.icloud.
cp /path/.uniprot_sprot.fasta.gz.icloud .
and now I don't know how to remove it from current directory as it would be removing '.' itself.
What can I do?
This doesn't work. It says: No such file or directory
rm .uniprot_sprot.fasta.gz.icloud
On the other hand:
ls -a
gives this:
.
..
uniprot_sprot.fasta.gz.icloud
You have not copied a file and renamed it . (at any rate if you're running a sane *nix). Instead you have copied the file to the current directory with the name of the original file. (If you pass a directory to cp as the destination, files will be placed in that directory. . is the current directory, so this is all that has happened.) If you want to remove it you can just rm uniprot_sprot.fasta.gx.iscloud or explicitly rm ./uniprot_sprot.fasta.gx.iscloud. What you have tried to do is to remove a file whose name starts with ., which is a different thing.
Edit: I was unaware when I wrote this, but this is in fact simply down to . existing as a real, regular hardlink. At syscall level you can create a file whose name contains anything except / and \x00 (yep, including \n), assuming your filesystem allows it. However, the links . and .. are already present and thus unavailable as a file name. #thatotherguy links to the kernel source for the rmdir syscall, showing that in modern Linux at least it is the kernel itself which ultimately prevents you from deleting . and ...
Note that in bash, . at the beginning of a line by itself means source.
See this question on unix.se and its linked dupe for more information on the filename problem.

How to find a file in a subdirectory where only the top level and a mid level directory are known

I'm trying to use bash to find a target file in a deep directory hierarchy whose top level directories and a mid-level directory are known but whose remaining directories may be of any arbitrary structure:
/A/B/[unknown]/[unknown]/.../C1/[unknown]/[unknown]/.../TargetFile
/A/B/[unknown]/[unknown]/.../C2/[unknown]/[unknown]/.../TargetFile
/A/B/[unknown]/[unknown]/.../C3/[unknown]/[unknown]/.../TargetFile
Let's say that I would like the path to TargetFile in the directory tree that includes directory C2. I made some crude but obviously flawed attempts with the find command, such as:
find '/A/B' -path '/C2/*' -name 'TargetFile'
Is there a way to accomplish this with find or with some other approach? (I am using the Mac OS version of the find command.)
With this example command you start a search from /home, and look for TargetFile contained in any directory named C2:
find /home -path '*/C2/*' -name 'TargetFile'

Find a file in Cygwin

I use find -name "nametofind" in cygwin to search for a file, but it does not give me any result, even when the file I want to search exists in the current directory. What am I doing wrong? Thanks.
As the comment mentioned more succinctly, you need to tell find which directory you want to search. If you it is the current directory, you should use ..
find . -name "nametofind"
It appears that the OP was trying to either match a partial file name or a file name with a different case. As #devnull mentioned in his comment, the correct solution for either case is to use the following.
find . -iname '*nametofind*'

What is the '.' directory in Windows?

For example, a directory has the following files: (as shown in explorer)
index.php
hello.php
img
If you query it using windows or just type dir in cmd prompt it will have the following files:
.
..
index.php
hello.php
img
I understand that '..' is a link to the previous directory, but what exactly is '.' and how can it be used? I've searched all over the internet, but no avail found for the single dot
The . can be used in some commands: This will copy the files from c:\temp to the current directory:
copy c:\temp\*.* .
The .. can be used to move to a higher directory.
This will change to the parent folder:
cd ..
The '.' indicates the current directory as per this. As you mentioned, '..' is a link to the previous directory. Ultimately the Operating System will choose how to indicate these, but it is pretty standard across all major OSs
. is the same as the current directory, but in a relative way.
For instance if the current directory is c:\temp and if you cd in this directory, then . == c:\temp.
In short . is the current directory and .. is the parent directory. It is convenient for you to write scripts with these keyword otherwise you have to write a long command.

Bash globbing - autoexpand for a few specific cases?

I understand that the wildcard * (by itself) will expand in such a way that it means "all non-hidden files in the current folder" with hidden files being those prefixed by a period.
There are two use cases that I would think are useful, but I don't know how to properly do:
How can you glob for... "All files in the current folder, including hidden files, but not including . or .."?
How can you glob for... "All hidden files (and only hidden files) in the current folder, but not including . or .."?
To expand on paviums answer and answer the second part of your question, all files except . and .. could be specified like this:
{.[!.]*,*}
Depending on your exact use case it might be better to set the dotglob shell option, so that bash includes dotfiles in expansions of * by default:
$ shopt -s dotglob
$ echo *
.tst
The Bash Cookbook suggests a solution to your 2nd requirement.
.[!.]*
as a way of specifying 'dot files' but avoiding . and ..
Of course, ls has the -A option, but that's not globbing.
Combining sth and pavium answers
# dot files but avoiding . and ..
.[!.]*
# all files but avoiding . and ..
{.[!.]*,*}
To meet your first case:
echo {.,}[^.]*
or
echo {.,}[!.]*
Edit:
This one seems to get everything, but is shorter than ephemient's
echo {.*,}[^.]*
By "all files" and "all hidden files" do you mean files-only, or do you mean both files and directories? Globbing operates on names irrespective of it belonging to a file or a directory. The other folks give good answers for using globbing to find hidden vs non-hidden names, but you may want to turn to the find command as an easier alternative that can distinguish between the types.
To find "All files in the current folder, including hidden files, but not including . or ..":
find . -type f
To find "All files and directories in the current folder, including hidden files, but not including . or ..":
find . ! -name .
To find "All hidden files (and only hidden files) in the current folder, but not including . or ..":
find . -name '.*' -type f
To find "All hidden files and directories (and only hidden files and directories) in the current folder, but not including . or ..":
find . -name '.*' ! -name .
Note that by default find will recurse through subdirectories, too, so if you want to limit it to only the current directory you can use:
find . -maxdepth 1 -type f
So, even though this is old - without using shopt, this doesn't seem to have been answered fully. But, expanding on what has been given as answers so far, these work for me:
1:
{*,.[!.]*,..?*}
2:
{.[!.]*,..?*}

Resources