How to stripe only file name from while using find command - linux

I'm Using find command in shell script to search a file from a directory.
FileList=`find /users/tst/CS/FSP/data/out/ -name "file*.gz"`
and I'm getting result as
echo $FileList
/users/tst/CS/FSP/data/out/filename.gz
I want result as "FileList=filetname.gz". I Would like to know how can we get it.

If you are using bash, you can use ## with parameter expansion and so:
FileList=$(while read fil;do echo ${fil##*/};done <<< $(find /users/tst/CS/FSP/data/out/ -name "file*.gz")"
ALternatively, if you have "basename" available, you could use it as follows:
FileList=$(while read fil;do echo "$(basename $fil)";done <<< $(find /users/tst/CS/FSP/data/out/ -name "file*.gz")"

Other possibilities (apart from the solutions already shown in Raman Sailopal's answer)
If you use GNU find as it should be the case on Linux, you can use find's -printf action.
FileList=$(find /users/tst/CS/FSP/data/out/ -name "file*.gz" -printf "%f")
If you only have a POSIX compatible find, you can filter the output.
FileList=$(find /users/tst/CS/FSP/data/out/ -name "file*.gz" | sed 's#.*/##')
The sed command will remove the longest part that ends with a /. (I use # instead of the ususal / to avoid quoting the / in the search pattern.)

FileList=find /users/tst/CS/FSP/data/out/ -name "file*.gz" -type f -name "file*.gz" | cut -d "/" -f 8

Related

Can't find a file by pattern [duplicate]

I am having a hard time getting find to look for matches in the current directory as well as its subdirectories.
When I run find *test.c it only gives me the matches in the current directory. (does not look in subdirectories)
If I try find . -name *test.c I would expect the same results, but instead it gives me only matches that are in a subdirectory. When there are files that should match in the working directory, it gives me: find: paths must precede expression: mytest.c
What does this error mean, and how can I get the matches from both the current directory and its subdirectories?
Try putting it in quotes -- you're running into the shell's wildcard expansion, so what you're acually passing to find will look like:
find . -name bobtest.c cattest.c snowtest.c
...causing the syntax error. So try this instead:
find . -name '*test.c'
Note the single quotes around your file expression -- these will stop the shell (bash) expanding your wildcards.
What's happening is that the shell is expanding "*test.c" into a list of files. Try escaping the asterisk as:
find . -name \*test.c
From find manual:
NON-BUGS
Operator precedence surprises
The command find . -name afile -o -name bfile -print will never print
afile because this is actually equivalent to find . -name afile -o \(
-name bfile -a -print \). Remember that the precedence of -a is
higher than that of -o and when there is no operator specified
between tests, -a is assumed.
“paths must precede expression” error message
$ find . -name *.c -print
find: paths must precede expression
Usage: find [-H] [-L] [-P] [-Olevel] [-D ... [path...] [expression]
This happens because *.c has been expanded by the shell resulting in
find actually receiving a command line like this:
find . -name frcode.c locate.c word_io.c -print
That command is of course not going to work. Instead of doing things
this way, you should enclose the pattern in quotes or escape the
wildcard:
$ find . -name '*.c' -print
$ find . -name \*.c -print
Try putting it in quotes:
find . -name '*test.c'
I see this question is already answered. I just want to share what worked for me. I was missing a space between ( and -name. So the correct way of chosen a files with excluding some of them would be like below;
find . -name 'my-file-*' -type f -not \( -name 'my-file-1.2.0.jar' -or -name 'my-file.jar' \)
I came across this question when I was trying to find multiple filenames that I could not combine into a regular expression as described in #Chris J's answer, here is what worked for me
find . -name one.pdf -o -name two.txt -o -name anotherone.jpg
-o or -or is logical OR. See Finding Files on Gnu.org for more information.
I was running this on CygWin.
You can try this:
cat $(file $( find . -readable) | grep ASCII | tr ":" " " | awk '{print $1}')
with that, you can find all readable files with ascii and read them with cat
if you want to specify his weight and no-executable:
cat $(file $( find . -readable ! -executable -size 1033c) | grep ASCII | tr ":" " " | awk '{print $1}')
In my case i was missing trailing / in path.
find /var/opt/gitlab/backups/ -name *.tar

How can I replace part of a path with a fixed string?

I wanna get directory name with minor change from path string in one line.
For example, if given string is
'./dir1/dir2/dir3/xxx.txt'
I wanna get
'./dir1/fix_string_as_suffix'
And I want to combine it with find command like below though it's not fixed yet.
find . -type d \( -name 'vendor' \) -prune -o -type f -name '*.txt' -print | cut -d'/' -f1,2
You can use sed:
s='./dir1/dir2/dir3/xxx.txt'
sed -E 's~^(([^/]*/){2}).*~\1~' <<< "$s"
./dir1/
Use IFS & printf Builtin
There's more than one way to do what you want within the shell, depending on whether you want to use standard utilities like cut, sed, or awk, or if you want limit yourself to expansions and builtins found within the shell itself. One approach is to split the path into components, and then rejoin them with the printf command or builtin. For example:
path='./dir1/dir2/dir3/xxx.txt'
IFS='/' read -ra dirs <<< "$path"
printf '%s' "${dirs[0]}/" "${dirs[1]}/" "..." $'\n'
If you want to turn this into a one-liner, join the commands with a semicolon and/or use curly braces for command grouping. However, readability trumps conciseness, especially in shell programming.
Use the cut command:
#!/bin/bash
path="./dir1/dir2/dir3/xxx.txt"
suffix="something fixed string"
prefix=`echo $path | cut -d/ -f1,2`
echo "$prefix/$suffix"
Concatenate lines from above using ; to get it on one line:
prefix=`echo $path | cut -d/ -f1,2` ; echo "$prefix/$suffix"
I think it's what you look for
find . -type d \( -name 'vendor' \) -prune -o -type f -name '*.txt' -exec sh -c 'echo "${1%/*}/fix_string_as_suffix"' fstrasuff {} \;
Actually, I ended up as below.
find . -type d \( -name 'vendor' \) -prune -o -type f -name '*.txt' -print | cut -d'/' -f1,2 | uniq | awk '{print $1"/..."}'

Yjw to replace and then search with sed and find

I'm making a bash script which would call like
script.sh 172.16.1.1
trying to replace . and search files to delete them but it won't happen
echo $1 | find -name '*.`sed 's/\.*//g'`' -printf "%f\n" -delete
files look like
eth0-2:120.1721611 eth1-2:120.1721611
Try this command inside that script.
I think this may help you for your requirement.
$ find -name "*echo "$1" | sed 's/\.*//g'" -printf "%f\n" -delete
I am passing the name only for the particular field, If you passed for whole command it produce the different result.
The given command is searched from current directory to end.
If you need to search from root or home use / or ~ in find command like
$ find ~ -name "*echo "$1" | sed 's/\.*//g'" -printf "%f\n" -delete

Terminal find Command: Manipulate Output String

I am trying to manipulate the filename from the find command:
find . -name "*.xib" -exec echo '{}' ';'
For example, this might print:
./Views/Help/VCHelp.xib
I would like to make it:
./Views/Help/VCHelp.strings
What I tried:
find . -name "*.xib" -exec echo ${'{}'%.*} ';'
But, the '{}' is not being recognized as a string or something...
I also tried the following:
find . -name "*.xib" -exec filename='{}' ";" -exec echo ${filename%.*} ";"
But it is trying to execute a command called "filename" instead of assigning the variable:
find: filename: No such file or directory
You can't use Parameter Expansion with literal string. Try to store it in a variable first:
find . -name '*.xib' -exec bash -c "f='{}' ; echo \${f%.xib}.strings" \;
-exec sees first argument after it as the command, therefore you can't simply give it filename='{}' because find doesn't use sh to execute what you give it. If you want to run some shell stuff, you need to use sh or bash to wrap up.
Or use sed:
find . -name '*.xib' | sed 's/.xlib$/.strings/'
For such a simple search, you can use a pure bash solution:
#!/bin/bash
shopt -s globstar
shopt -s nullglob
found=( **.xib )
for f in "${found[#]}"; do
echo "${f%xib}strings"
done
Turning the globstar shell option on enables the ** to "match all files and zero or more directories and subdirectories" (as quoted from the bash reference manual). The nullglob option helps if there's no match: in this case, the glob will be expanded to nothing instead of the ugly **.xib. This solution is safe regarding filenames containing funny characters.
find . -name "*.xib" | sed -e 's/\.xib$/.strings/'

list the file and its base directory

I have some files in my folder /home/sample/* * /*.pdf and *.doc and * .xls etc ('**' means some sub-sub directory.
I need the shell script or linux command to list the files in following manner.
pdf_docs/xx.pdf
documents/xx.doc
excel/xx.xls
pdf_docs, documents and excel are directories, which is located in various depth in /home/sample. like
/home/sample/12091/pdf_docs/xx.pdf
/home/sample/documents/xx.doc
/home/excel/V2hm/1001/excel/xx.xls
You can try this:
for i in {*.pdf,*.doc,*.xls}; do find /home/sample/ -name "$i"; done | awk -F/ '{print $(NF-1) "/" $NF}'
I ve added a line of awk which will print the last 2 fields (seperated by '/' ) of the result alone
Something like this?
for i in {*.pdf,*.doc,*.xls}; do
find /home/sample/ -name "$i";
done | perl -lnwe '/([^\/]+\/[^\/]+)$/&&print $1'
How about this?
find /home/sample -type f -regex '^.*\.\(pdf\|doc\|xls\)$'
Takes into account spaces in file names, potential case of extension
for a in {*.pdf,*.doc,*.xls}; do find /home/sample/ -type f -iname "$a" -exec basename {} \; ; done
EDIT
Edited to take into account only files
You don't need to call out to an external program to chop the pathname like you're looking for:
$ filename=/home/sample/12091/pdf_docs/xx.pdf
$ echo ${filename%/*/*}
/home/sample/12091
$ echo ${filename#${filename%/*/*}?}
pdf_docs/xx.pdf
So,
find /home/sample -name \*.doc -o -name \*.pdf -o -name \*.xls -print0 |
while read -r -d '' pathname; do
echo "${pathname#${pathname%/*/*}?}"
done

Resources