Tag Info

Hot answers tagged

43

Use the ? wildcard for file globbing: ls -d /tmp/???? This will print all files and directories whose filename is 4-char long. As suggested by @roaima, the -d flag will prevent ls to display the content of subdirectories that match the pattern.


11

You can prevent the file from reaching xargs using: find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\n' | xargs -r shasum -- > sums.sha1 To prevent problems with filename that have blanks or newlines or quotes or backslashes, I would however use: find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\0' | xargs -r0 shasum -- > ...


10

List files in /tmp only: cd /tmp find . ! -name . -prune -path './????' -type f List files in /tmp recursively: find /tmp -path '*/????' -type f


8

The basic format of find is find WHERE WHAT So, in find *, the * is taken as the WHERE. Now, * is a wildcard. It matches everything in the current directory (except, by default, files/directories starting with a .). The Windows equivalent is *.*. This means that * is expanded to all files and directories in your current directory before it is passed to ...


7

If you understand the && and || operators in the shell (and also in C, C++, and derivative languages), then you understand -a and -o in find. To refresh your memory: In the shell, command1 && command2 runs command1, and, if it (command1) succeeds, it (the shell) runs command2. command1 || command2 runs command1, and, if it (command1) fails, ...


7

Try this: find /tmp/ -type f -name "*.h" -o -name "*.cpp" \ -exec sed -i '1s/^/#include <stdint.h>\n/' {} + Also, as correctly pointed out to me, the ! -name "*.bak" is superfluous. The -name *foo pattern only matches files ending with foo. Therefore, the *.cpp and *.h already exclude *.bak.


6

It looks like you want to avoid looking for files in *cache* directories more than finding files with *pillar* and not *cache* in their name. Then, just tell find not to bother descending into *cache* directories: find . -iname '*cache*' -prune -o -iname '*pillar*' -print Or with zsh -o extendedglob: ls -ld -- (#i)(^*cache*/)#*pillar* (not strictly ...


6

The find options you've specified apply on the filename, not on the name of sub-directories. Here, your filename doesn't contain cache but contains pillar, so it matches. In your case, you may want to use the -path option. Something like: find . -iname '*pillar*' -and -not -ipath '*cache*'


6

Try: find /tmp -type f -print| awk -F/ ' length($NF) == 4 ' What awk does: Using / as field separator, Finding filename $NF (last field) Computing length And check if value is 4, then print it.


6

These are not part of bash; find is a standalone program and does not require bash or even a POSIX shell to run. For example, it works fine with fish, which is not POSIX compliant and does not follow all the same syntax rules as bash. You could, in fact, use it with no shell at all (e.g., in a programmatic context). This is why (if you are using a POSIX ...


5

On GNU/anything, ls -l --time-style=+%s \ | awk '{$6 = int($6/86400); print}' \ | sort -nk6,6 -nrk5,5 \ | sort -sunk6,6 That will get you UTC boundaries, add your local time offset to the calc as needed,e.g. int(($6-7*3600)/86400) for -0700 midnight boundaries.


5

The order of find arguments matters. The command needs to be constructed as find -type d -print0 and then it will work as expected. I just thought I'd post this in case it's helpful to anyone.


5

Since you're using -maxdepth 1, I assume you don't want recursion. If so, just do it in the shell instead: for f in ~/test/*; do shasum -- "$f" done > sums.sha1 To skip directories, you can do: for f in ~/test/*; do [ ! -d "$f" ] && shasum -- "$f" done > sums.sha1 If you do need recursion and are using bash, do: shopt -s globstar ...


4

This seems to me like the most straightforward way to find a file of four bytes: find /tmp -type f -size 4c Edit: to find a file name of four bytes: find /tmp -type f -name '????'


4

Use find -exec for recursive touch, with command line args for dirs to process. #!/bin/sh for i in "$@"; do find "$i" -type f -exec touch -r {} -d '+3 hour' {} \; done You can run it like this: ./script.sh /path/to/dir1 /path/to/dir2


4

Don't use find for this - whichever way you go with find you'll need something like a single mv per file. That's a lot of processes, and to no benefit. This is not to mention that it is simply more difficult to do that way. That's my opinion, anyway. I would use a stream or a batch tool, and tend to prefer pax: cd -P . && mkdir ../newmp4 ...


4

Although both curly braces {,} and semicolons ; do have special meanings in bash, in this case it is the find command itself that is interpreting them, not the shell. The -ok command of find uses the same syntax as its -exec command, so you will find a complete description in that section of its manual page (man find): -exec command ; Execute ...


4

with zsh: shasum -- *(D.) > sums.sha1 The glob will be expanded before the redirection is made, so the sums.sha1 will not be included if it was not there in the first place. D is to include dot-files (hidden files) as find would. . is to select only regular files (like your -type f). To exclude the sums.sha1 anyway in case it was there in the first ...


4

The GNU implementation of grep (also found in most modern BSDs though the latest versions are a complete (mostly compatible) rewrite) supports a -o option to output all the matched portions. LC_ALL=C grep -ao CDA | wc -l would then count all the occurrences. LC_ALL=C grep -abo CDA to locate them with their byte offset. LC_ALL=C makes sure grep doesn't ...


4

You can use -o for logical OR. Beware however that all find predicates have logical values, so you'll usually need to group ORed things together with parens. And since parens also have a meaning to the shell, you'll also need to escape them: find /some/dir -maxdepth 1 \( -name '*.c' -o -name '*.h' \) -print


3

You could do: find . -name '*.png' | awk -F/ '{print tolower($NF)}' | sort -u > ~/tmp/png-files && grep -IhFriof ~/tmp/png-files --exclude-dir=".svn" . | awk '{print tolower($0)}' | sort -u | comm -23 ~/tmp/png-files - That would give you the lower-case names of the png files that are never referenced. The first pipeline builds a sorted ...


3

The example in your question looks like the ls -l output, not the lsattr output. In the ls -l output, the first field is the mode, that is the type (regular, directory, symlink...) and permissions. The S bit at that position means setuid but without execute permission for the user. Here given that none of user/group/other have execute permissions, that ...


3

find -perm Is what you want - it'll allow you to specify an octal mode for 'find' to ... well, find. You can find which perm to look for with 'stat' which will give you what it currently is. So e.g. find . -perm 4750 I don't recognise your bit flags well enough to tell you the octal mode of them, so you'll have to look for yourself. Edit: As ...


3

You should decompose your goal into several steps easier to solve. This will have two advantages: It will be easier to solve, The resulting code will be clearer and more reusable. The scripts below basically follows these steps: Generate raw statistic files. An easy way is to append the file size and the file name in a temporary file named after the ...


3

There's also a perl (5.10 or newer) solution: perl -E 'say for </tmp/????>;' A slightly more flexible version where you can specify the desired length: perl -E 'my $w = "?" x shift; say for </tmp/$w>;' 4


3

You could use : find . -name .git -prune -o -type f -exec sed -i 's/_backpack.html/_backpack_cal.html/g' {} + I added the -name .git -prune section which basically means "if the name of the directory is .git, do not process that directory." Also, please note the added -o (meaning or) which only executes your statement if the first one is false (ie if the ...


3

I'd use1 find with two -exec actions e.g.: find . -type f -exec grep -qF SOME_STRING {} \; -exec sed 'COMMAND' {} \; The second command will run only if the first one evaluates to true i.e. exit code 0 so sed will process the file in question only if the file contains SOME_STRING. It's easy to see how it works: find . -type f -exec grep -qF SOME_STRING {} ...


2

An approach based on stat to obtain the file information and awk to determine the maximum for each date: stat -c $'%.10y\t%s\t%n' * | awk 'BEGIN { FS=OFS="\t" } s[$1]<$2 { s[$1]=$2 ; n[$1]=$3 } END { for (d in n) print d,s[d],n[d] | "sort" }' The output will be a Tab separated list of (date, size, filename) tuples.


2

Assuming you're using bash, you can do the following: shopt -s globstar shopt -s nullglob filearray=(/tmp/**/????) This will put the list of files you want in an array filearray. Newlines (and other exotic characters) in the filename will be handled correctly. Setting globstar enables ** in glob patterns to match across subdirectories, giving the ...


2

"/tmp/" takes 5 characters. That's why there is "9" (5+4) in test for i in /tmp/* ; do [ "${#i}" -eq 9 ] && printf %s\\n "$i"; done or for i in /tmp/* ; do i="${i#/tmp/}"; # to get rid of /tmp/ [[ "${#i}" -eq 4 ]] && printf %s\\n "$i"; # there is 4 in test! done FWIW. It does not fail on newline (@cuonglm), can be easilly ...



Only top voted, non community-wiki answers of a minimum length are eligible