Hot answers tagged

31

You only need the shell for this job. POSIXly: for f in *.png; do printf '%s\n' "${f%.png}" done With zsh: print -rl -- *.png(:r)


29

There are two problems with your example. The primary one is that you're assuming that regular expressions work the same as glob patterns in that * is a wildcard meaning "any sequence of characters." In regular expressions, * means "any number of the previous atom" instead, so fil* means f followed by i followed by zero or more l characters. You need to say ...


20

ls -1 | sed -e 's/\.png$//' The sed command removes (that is, it replaces with the empty string) any string .png found at the end of a filename. The . is escaped as \. so that it is interpreted by sed as a literal . character rather than the regexp . (which means match any character). The $ is the end-of-line anchor, so it doesn't match .png in the ...


13

If you just want to use bash: for i in *; do echo "${i%.png}"; done You should reach for grep when trying to find matches, not for removing/substituting for that sed is more appropriate: find . -maxdepth 1 -name "*.png" | sed 's/\.png$//' Once you decide you need to create some subdirectories to bring order in your PNG files you can easily change that ...


10

A way using perl which will respect backslashes v="$1" perl -ne 'print if index($_, $ENV{"v"} )==0' file This sets the environment variable v for the command, then prints if the index of the variable is 0 i.e the beginning of the line. You can also do identical in awk v="$1" awk 'index($0, ENVIRON["v"])==1' file


9

If you only need to check whether or not a match is found, cut all input lines to the length of the desired prefix ($1) and then use fixed-pattern grep: if cut -c 1-"${#1}" | grep -qF "$1"; then echo "found" else echo "not found" fi It's also easy to get the count of matching lines: cut -c 1-"${#1}" | grep -cF "$1" Or the line numbers of all ...


9

Another very similar answer (I'm surprised this particular variant hasn't appeared yet) is: ls | sed -n 's/\.png$//p' You don't need the -1 option to ls, since ls assumes that if the standard output isn't a terminal (it's a pipe, in this case). the -n option to sed means ‘don't print the line by default’ the /p option at the end of the substitution means ...


8

I'd go for basename (assuming the GNU implementation): basename --suffix=.png -- *


7

I can't think of a way to do this using grep; ^ itself is part of a regular expression so using it requires regular expressions to be interpreted. It's trivial using substring matching in awk, perl or whatever: awk -v search="$1" 'substr($0, 1, length(search)) == search { print }' To handle search strings containing \, you can use the same trick as in ...


6

This is a GNU extension. From the grep(1) manpage: In GNU grep, there is no difference in available functionality between basic and extended syntaxes. In other implementations, basic regular expressions are less powerful. The following description applies to extended regular expressions; differences for basic regular ...


6

Here's an all-bash option, not that I recommend bash for text-processing, but it works. #!/usr/bin/env bash # searches for $1 at the beginning of the line of its input len=${#1} while IFS= read -r line do [[ "${line:0:len}" = "$1" ]] && printf "%s\n" "$line" done The script computes the length len of the inputted parameter $1, then uses ...


6

\< and \> match empty string at the begin and end of a word respectively and only word constituent characters are: [[:alnum:]_] From man grep: Word-constituent characters are letters, digits, and the underscore. So, your Regex is failing because / is not a valid word constituent character. Instead as you have spaces around, you can use -w option ...


5

You can use only BASH commands to do that (without any external tools). for file in *; do echo "${file%.*}"; done This is usefully when you're without /usr/bin and works nice for filenames like this.is.image.png and for all extensions.


4

Here is a version that is safe for names with whitespace: find /var/log/folder -type f -printf '%T@ %p\0' | sort -rz | sed -Ezn '1s/[^ ]* //p' | xargs --null grep string How it works: find /var/log/folder -type f -printf '%T@ %p\0' This looks for files and prints their modification time (seconds) followed by a space and their name followed by a nul ...


4

wasn't it enough? ls -1 | sed 's/\.png//g' or in general, this ls -1 | sed 's/\.[a-z]*//g' will remove all extensions


3

ls -1rt /path/to/files/ | tail -n1 will find the newest file in a directory (in terms of modification time); pass that as an argument to grep: grep 'string to find' "$(ls -1rt /path/to/files/ | tail -n1)"


3

dirname of file is missing in first part, try grep -w 'sucessfully completed.' "/var/log/folder/$(ls -1rt /var/log/folder | tail -n1)" do not try ... unles there is no dir in /var/log/folder/ grep -w 'sucessfully completed.' "$(ls -1rt /var/log/folder/* | tail -n1)"


3

So many options, pick the one you like. Using grep: grep -o '^[^:]\+:[^:]\+' file.txt using cut: cut -d: -f1-2 file.txt using awk: awk -F: '{ print $1$2 }' file.txt using sed: sed 's/^\([^:]\+:[^:]\+\).*/\1/' file.txt using shell: while IFS=: read -r i j k; do echo "$i$j"; done <file.txt using perl: perl -pe 's/^([^:]+:[^:]+).*/$1/' ...


3

Is this what you mean? find ~/ops_scripts -type f -maxdepth 1 -name "*ScheduledJobs*.txt"


3

Problem : * is not getting expanded ; there really is no such file named * , so grep reports that. Solution : remove the last * ; it will work with -r , making grep look into all the files in that Directory.


2

--exclude-dir does not understand |. You can, however, get the same effect by specifying --exclude-dir multiple times, one for each directory that you want to exclude: grep -inRw -E --exclude-dir 'asset' --exclude-dir 'git' --exclude-dir 'log' 'direct'


2

If your $1 is pure ASCII and your grep has the -P option (to enable PCRE), you can do this: #!/bin/bash line_start="$1" line_start_raw=$(printf '%s' "$line_start" | od -v -t x1 -An) line_start_hex=$(printf '\\x%s' $line_start_raw) grep -P "^$line_start_hex" The idea here is that grep -P allows regular expressions with \xXX to specify literal ...


2

As a filter: perl -ne 'BEGIN {$pat = shift} print if /^\Q$pat/' search-pattern Run on one or more files: perl -ne 'BEGIN {$pat = shift} print if /^\Q$pat/' search-pattern file.. The “Quoting metacharacters” section of the perlre documentation explains: Quoting metacharacters Backslashed metacharacters in Perl are alphanumeric, such as \b, \w, ...


2

If there is a a character that you don't use, you could use that to mark the beginning of the line. For example, $'\a' (ASCII 007). It's ugly but it will work: { echo 'this is a line to match'; echo 'but this is not'; } >file.txt stuffing=$'\a' # Guaranteed never to appear in your source text required='this' # What we want to match that beginning ...


2

Within the script itself would require a redirection trick: #!/bin/bash exec 1> >(tee >(awk '/STOP/{system("kill '"$$"'")}')) while read line; do echo $line sleep 1 done And thence: bash-4.1$ (echo can; echo t; echo STOP; echo believing) | bash datscript Another option might be expect, e.g. something like #!/usr/bin/env expect spawn ...


2

test.awk: FNR == NR{ names[$1] next } ($1 in names){ ulog[$1]++ } END{ for(name in ulog){ print name ":" ulog[name] } } and run it as awk -f test.awk user.list user.log FNR==NR # does the file record number == the record number, if it does then we are still in the first file next # as we are still in the first file, skip the ...


2

Something simple like: mapfile -t names < file1 for name in "${names[@]}" do echo "${name}" $(grep -c "^$name " file2) done Will provide output like: Peht 2 Mawo 3 Stso 1 Makr 0 Bavo 2 The grep string says to anchor the username at the beginning (^) of the line, and enforce a trailing space after the line.


2

You can use grep -B2 -E '^[0-9]{5} +[a-zA-Z]+$' to try to find only address blocks. Some notes: see man grep to get an understanding of the options see the end of the manpage for grep to find a manpage that explains the regex syntax in detail, the GNU grep manpage itself also explains regex a little -B is "lines before the match" and might be better ...


2

You could try like this sed '/Queue/{N;$d;N;$d;N;/==$/d}' infile This just pulls in the next three lines when line matches Queue. If the pattern space ends with a separator1 it deletes it (or if either2 the 1st line or the 2nd line pulled in is the last one in the input). If other lines may end with consecutive = signs you should replace the ==$ in the ...


2

Even though this is an old question, it seems to me it's a perennial question, and a more general, clearer solution is available than has been suggested so far. Credit where credit is due: I'm not sure I would have come up with it without considering Stéphane Chazelas's mention of the <> update operator. Opening a file for update in a Bourne shell ...



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