Please refer to the Filesystem Hierarchy Standard (FHS) for Linux for this.
/bin
: For binaries usable before the /usr
partition is mounted. This is used for trivial binaries used in the very early boot stage or ones that you need to have available in booting single-user mode. Think of binaries like cat
, ls
, etc.
/sbin
: Same, but for binaries with superuser (root) privileges required.
/usr/bin
: Same as first, but for general system-wide binaries.
/usr/sbin
: Same as above, but for binaries with superuser (root) privileges required.
if I'm writing my own scripts, where should I add these?
None of the above. You should use /usr/local/bin
or /usr/local/sbin
for system-wide available scripts. The local
path means it's not managed by the system packages (this is an error for Debian/Ubuntu packages).
For user-scoped scripts, use ~/bin
(a personal bin folder in your home directory).
The FHS says for /usr/local
:
Tertiary hierarchy for local data, specific to this host. Typically has further subdirectories, e.g., bin/
, lib/
, share/
.
I haven't examined the output with symlinks but:
find . -type f -iname '*.c' -printf '%h\0' |
sort -z |
uniq -zc |
sed -zr 's/([0-9]) .*/\1 1/' |
tr '\0' '\n' |
awk '{f += $1; d += $2} END {print f, d}'
- The
find
command prints the directory name of each .c
file it finds.
sort | uniq -c
will gives us how many files are in each directory (the sort
might be unnecessary here, not sure)
- with
sed
, I replace the directory name with 1
, thus eliminating all possible weird characters, with just the count and 1
remaining
- enabling me to convert to newline-separated output with
tr
- which I then sum up with awk, to get the total number of files and the number of directories that contained those files. Note that
d
here is essentially the same as NR
. I could have omitted inserting 1
in the sed
command, and just printed NR
here, but I think this is slightly clearer.
Up until the tr
, the data is NUL-delimited, safe against all valid filenames.
With zsh and bash, you can use printf %q
to get a quoted string, which would not have newlines in it. So, you might be able to do something like:
shopt -s globstar dotglob nocaseglob
printf "%q\n" **/*.c | awk -F/ '{NF--; f++} !c[$0]++{d++} END {print f, d}'
However, even though **
is not supposed to expand for symlinks to directories, I could not get the desired output on bash 4.4.18(1) (Ubuntu 16.04).
$ shopt -s globstar dotglob nocaseglob
$ printf "%q\n" ./**/*.c | awk -F/ '{NF--; f++} !c[$0]++{d++} END {print f, d}'
34 15
$ echo $BASH_VERSION
4.4.18(1)-release
But zsh worked fine, and the command can be simplified:
$ printf "%q\n" ./**/*.c(D.:h) | awk '!c[$0]++ {d++} END {print NR, d}'
29 7
D
enables this glob to select dot files, .
selects regular files (so, not symlinks), and :h
prints only the directory path and not the filename (like find
's %h
) (See sections on Filename Generation and Modifiers). So with the awk command we just need to count the number of unique directories appearing, and the number of lines is the file count.
Best Answer
cp *.prj ../prjshp/
is the right command, but you've hit a rare case where it runs into a size limitation. The second command you tried doesn't make any sense.One method is to run
cp
on the files in chunks. Thefind
command knows how to do this:find
traverses the current directory and the directories below it recursively.-maxdepth 1
means to stop at a depth of 1, i.e. don't recurse into subdirectories.-name '*.prj'
means to only act on the files whose name matches the specified pattern. Note the quotes around the pattern: it will be interpreted by thefind
command, not by the shell.-exec … {} +
means to execute the specified command for all the files. It invokes the command multiple times if necessary, taking care not to exceed the command line limit.mv -t ../prjshp
moves the specified files into../prjshp
. The-t
option is used here because of a limitation of thefind
command: the found files (symbolized by{}
) are passed as the last argument of the command, you can't add the destination after it.Another method is to use
rsync
.rsync -r … . ../prjshp
copies the current directory into../prjshp
recursively.--include='*.prj' --exclude='*'
means to copy files matching*.prj
and exclude everything else (including subdirectories, so.prj
files in subdirectories won't be found).