The Stack Overflow podcast is back! Listen to an interview with our new CEO.

New answers tagged

0

So just to wrap up this question the answer is to set LC_COLLATE as @don_crissti mentioned in the comment: $ LC_COLLATE=C sort infile


3

To copy regular files (excluding hidden dot files) in your current directory starting with UnityFS5, you could use: for file in *; do if [ -f "$file" ] && [ "$(head -c 8 "$file")" = "UnityFS5" ]; then cp "$file" /path/to/destination/ fi done


1

Actually, reading your comments, it’s not a real hosts file, but just a list of domin names, so you seem to be satisfied filtering all lines with at least two dots: grep '\..*\.' hostfile If it is important that the domain is at the beginning of the line, use grep '^[[:alnum:]]*\..*\.' hostfile


2

/etc/hosts entries can have one or more hostnames per IP address, so we need to check each hostname (i.e. all fields except the first field) to see if it has 2 or more . characters in it. For example: awk '{for (f=2;f<=NF;f++) {if (split($f,array,/\./)>2) {print;last}}}' /etc/hosts or, with linefeeds and indentation added to improve readability: ...


1

If this is Unix, you could type "which Minecraft". If it is Windows, you could type ""where Minecraft". Add --all to the which command to list all the programs not just the first. Both programs search the PATH or in the case of Windows, the path plus certain runtime registry locations. To find programs in places beyond the path, do the find command above, ...


1

Using find and dirname to locate all files with the name minecraft in the current directory (adjust the search location to suit). find . -type f -name minecraft | xargs -L 1 dirname For finding files with executable permissions, you can use the -perm option for find (adjust the value to suit your search criteria): find . -type f -perm +0111 -name ...


0

Barrett 2012 says on page 74: "-printfstring print the given string, which may have substitutions applied to it in the manner of the C library function printf()." and recommends, of course, the manpage for the full list of options. While things like find . -printf '%s %p\n' get explained, others dont. @jim has mentioned the use of %T. I personally use ...


1

For zsh users: rm -v **/*(-@) from zsh user guide (search for broken symlinks)


1

Wildcards are expanded by the shell, not by the command. find is one of the few commands that performs wildcard matching that's similar to the shell, in its own time. When you run ls *.xml, first the shell expands *.xml to the list of matching files, e.g. file1.xml file2.xml file3.xml, and then the shell calls ls with the resulting list of arguments file1....


2

Wildcards are expanded by the shell, not by the command. find is one of the few commands that performs wildcard matching that's similar to the shell, in its own time. When you run ls *.jav, first the shell expands *.jav to the list of matching files, e.g. file1.jav file2.jav file3.jav, and then the shell calls ls with the resulting list of arguments file1....


0

Thank you all for the answers. I figured out the 2 files are indeed hard linked with each other(share the same inode no#) So, Find / -name (filename) will not list the other hard linked files scattered around the server suggest using Find / -samefile (filename) to find the other hard-linked files.


2

In find . -name "foo*" -exec tail -1 {} \; -exec nemo {} + you are executing tail on the contents of each file found, rather than on the list of filenames. At lease with GNU Coreutils, you could do something like find . -name "foo*" -print0 | tail -zn 1 | xargs -0 nemo


3

In your command find . -name "binaries.tgz.*.gz" -exec gzip -d -k < {} \; the < {} is interpreted by the shell before running find. Use find . -name "binaries.tgz.*.gz" -exec gzip -d -k {} \; to extract all files and keep the original ones. You can try find . -name "binaries.tgz.*.gz" -type f -exec gzip -d -c {} \; | tar tzf - to extract to ...


1

If you’re using GNU grep, the -H option will ensure that the output is prefixed with the filename in all cases: find . -type f -name "*.py" -exec grep -H "word" {} \; Incidentally, you could use + here instead of \; to run grep on as many files as possible at a time: find . -type f -name "*.py" -exec grep -H "word" {} +


0

Using zsh: setopt extendedglob nullglob for pathname in /**/*(/e{'[[ -n $REPLY/(#i)*.htm(l#)(#q.) ]]'}); do printf '%s:\n' $pathname ls -l $pathname done This prints the pathname of each directory containing any regular file whose name ends with either .htm or .html (regardless of case), followed by the ls -l output for that directory. The loop ...


2

-perm /102 will simply match files which have any of those bits set, as described in the manpage. To achieve what you want, you need two -perm predicates; one that excludes your "no" permissions, and one which includes your "yes" permission: find ... \! -perm /070 -perm /006


1

Use find's -exec directive to process the moves: The filenames will not be split by spaces. find "$srcDir" -type f -mtime 1 -exec echo mv -t "$destDir" {} + # ....... remove echo if it looks OK: ^^^^


4

Think of aliases as substituting a word with some other text in shell code before it is interpreted. With a find alias defined as: alias find='function _find(){find / -name "$1" 2>&1 | grep -v "Permission denied"}' When you type find at the prompt, that gets substituted with: function _find(){find / -name "$1" 2>&1 | grep -v "Permission ...


1

alias find='function _find() { find / -name "$1" 2>&1 | grep -v ": Permission denied$"; } ; _find' Your alias defines a function. You want it do define a function and call it.


0

ag (the silver searcher) provides very fast search in files, and also has an option to search for filename: >: time ag -g foo # uses heuristics to only look in desired locations apps/vxy/src/assets/tree-content-pages/tree-page-bird/foo-illustration.jpg real 0m0.884s user 0m0.701s sys 0m0.178s >: time find . -name "*foo*" ./apps/ssr/dist/...


0

The accepted answer is helpful, but if your filenames are already in the encoding specified in LANG/LC_CTYPE, it's better to just do: LC_COLLATE=C find . -name '*[! -~]*' Character classes are affected by LC_CTYPE, but the above command does not use character classes, only ranges, so LC_CTYPE just prevents the unusual characters from being replaced by ...


1

Use rename instead: find . -maxdepth 1 -type f -exec rename 'y/a-z/A-Z/' {} + The {} will not expand in your subshell.


3

I think the most generalizable approach is to build a simple one-liner shell command to send to find: find . -name "*.txt" -exec sh -c 'cat {} >> foobar && rm {}' A side note: Your glob *.txt matched your output file, all.txt. You'll avoid edge cases if the file you're appending too (foobar in my case) doesn't match your -name glob. Just ...


0

A single line script is also an option: find -type f -name "*.pdf" -exec bash -c 'gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -dQUIET -sOutputFile="new.pdf" "{}"; rm "{}"; mv "new.pdf" "{}";' {} \;


0

Finding files based on the date contained in their filenames In case what you mean is really to filter on date in filenames, then you can do this: #!/bin/bash read -p "Enter year (YYYY): " Y read -p "Enter start month number: " SM read -p "Enter start day number: " SD read -p "Enter end month number: " EM read -p "Enter end day number: " ED read -p "...


3

-or has lower precedence than -and (which is the default connector), so you need to explicitly increase your disjunction’s “priority”: find . -path "./dist" -prune -or \( -iname "*.js" -or -iname "*.jsx" \) -exec grep "foo" {} +


3

Try this, find . -iname '*.zip' -printf '%p %TY/%Tm/%Td %.8TT\n' > zipfiles.txt


2

With the GNU implementation of find, you can do: find . -iname '*.zip' -printf '%p %TFT%TT%Tz+\n' which gives an output like: ./file.zip 2018-03-04T13:23:21.0321012380+0000


0

You could use -iregex instead of multiple -inames. e.g. using extended regular expressions: GNU find: find . -type f -regextype egrep -iregex '.*\.(ksh|cfg)$' FreeBSD find: find -E . -type f -iregex '.*\.(ksh|cfg)$' If you already have the extensions comma-separated in a variable (e.g. $csep), convert them to regexp alternations (|). first. e.g ...


2

Assuming that you get the filename suffixes as separate command line arguments (see end of answer for how to deal with a comma-delimited string instead): #!/bin/sh for suffix do set -- "$@" -o -iname "*.$suffix" shift done shift find . -type f \( "$@" \) This script wold be called as ./script.sh ksh cfg and it would replace each suffix $suffix ...


1

In a directory you can find the "stems" with: ls * | sed -r 's/[0-9]+$//' | sort | uniq For each stem you can list all files with the last with: ls FILE_1-* | head -n -1 Or if you want to keep the most recent: ls -rt FILE_1-* | head -n -1 Both commands can be followed by | xargs rm to delete their output Put all that in a short script(*) and run: ...


2

If you wanted the cumulative disk usage (as your usage of du suggests) of the regular files that are over 60 days old and need only to be portable to GNU and busybox systems (though note that which commands are included in busybox and what feature they support is configurable at build time, so you can never know if what works with one instance of busybox ...


3

In principle this is easy: just tell find to run du on a bunch of files at once. find . -type f -mtime +60 -exec du -smc {} + Unfortunately this doesn't work reliably, because -exec … {} + can execute the command multiple times, it only tries to group the arguments, and it cannot possibly group all the arguments if their total length would go over the system'...


3

Try pipe the output of find to du and specify the --files0-from - flag: find -type f -mtime +60 -print0 | du -shc --files0-from - This should give you a grand total at the end To get just the total, pipe that output to tail -n1: find -type f -mtime +60 -print0 | du -shc --files0-from - | tail -n1 I should mention that I actually just tested this with ...


0

It works if you use add a SRC argument (the . as source directory): rsync --files-from=<(find . -type f \( -name "*.X" -o -name "*.x1" \) -mtime -30) . user@x.x.x.x:/where/to/put/files


2

Assuming the directories are not nested, loop through the directories and check for the presence of the file in each directory. for d in */; do if ! [ -e "$d/20190916.file.gz" ]; then echo "Missing $d/20190916.file.gz" fi done


Top 50 recent answers are included