Using wildcard with 'ls' - linux

I want to list the all files having a name like these:
12.0.3.1_CA
12.0.3.2A_CA
12.0.3.2B_CA
I tried
ls -ltr 12.0.3.?*_CA
That worked, but fails when I have files like:
12.0.3.2AA_CA
12.0.3.2A2_CA

If you want only one character at max after the '?' then try:
ls -ltr 12.0.3.?[*]_CA
[] is used to encase any character you want, like if we want to have 'ac' in the name we would use [ac].

Related

How do I exclude a character in Linux

Write a wildcard to match all files (does not matter the files are in which directory, just ask for the wildcard) named in the following rule: starts with a string “image”, immediately followed by a one-digit number (in the range of 0-9), then a non-digit char plus anything else, and ends with either “.jpg” or “.png”. For example, image7.jpg and image0abc.png should be matched by your wildcard while image2.txt or image11.png should not.
My folder contained these files imag2gh.jpeg image11.png image1agb.jpg image1.png image2gh.jpg image2.txt image5.png image70.jpg image7bn.jpg Screenshot .png
If my command work it should only display image1agb.jpg image1.png image2gh.jpg image5.png image70.jpg image7bn.jpg
This is the command I used (ls -ad image[0-9][^0-9]*{.jpg,.png}) but I'm only getting this image1agb.jpg image2gh.jpg image7bn.jpg so I'm missing (image1.png image5.png)Kali Terminal and what I did
ls -ad image[0-9][!0-9]*{.jpg,.png}
Info
Character ranges like [0-9] are usually seen in RegEx statements and such. They won't work as shell globs (wildcards) like that.
Possible solution
Pipe output of command ls -a1
to standard input of the grep command (which does support RegEx).
Use a RegEx statement to make grep filter filenames.
ls -a1|grep "image"'[[:digit:]]\+[[:alpha:]]*\.\(png\|jpg\)'

Pick the specific file in the folder

I want pick the specific format of file among the list of files in a directory. Please find the below example.
I have a below list of files (6 files).
Set-1
1) MAG_L_NT_AA_SUM_2017_01_20.dat
2) MAG_L_NT_AA_2017_01_20.dat
Set-2
1) MAG_L_NT_BB_SUM_2017_01_20.dat
2) MAG_L_NT_BB_2017_01_20.dat
Set-3
1) MAG_L_NT_CC_SUM_2017_01_20.dat
2) MAG_L_NT_CC_2017_01_20.dat
From the above three sets I need only 3 files.
1) MAG_L_NT_AA_2017_01_20.dat
2) MAG_L_NT_BB_2017_01_20.dat
3) MAG_L_NT_CC_2017_01_20.dat
Note: There can be multiple lines of commands because i have create the script for above req. Thanks
Probably easiest and least complex solution to your problem is combining find (a tool for searching for files in a directory hierarchy) and grep (tool for printing lines that match a pattern). You also can read those tools manuals by typing man find and man grep.
Before going straight to solution we need to understand, how we will approach your problem. To find pattern in a name of file we search we will use find command with option -name:
-name pattern
Base of file name (the path with the leading directories removed) matches shell pattern pattern. The metacharacters ('*', '?', and '[]')
match a '.' at the start of the base name (this is a change in
findutils-4.2.2; see section STANDARDS CONFORMANCE below). To ignore a
directory and the files under it, use -prune; see an example in the
description of -path. Braces are not recognised as being special,
despite the fact that some shells including Bash imbue braces with a
special meaning in shell patterns. The filename matching is performed
with the use of the fnmatch(3) library function. Don't forget to
enclose the pattern in quotes in order to protect it from expansion by
the shell.
For instance, if we want to search for a file containing string 'abc' in directory called 'words_directory', we will enter following:
$ find words_directory -name "*abc*"
And if we want to search all directories in directory:
$ find words_directory/* -name "*abc*"
So first, we will need to find all files, which begin with string "MAG_L_NT_" and end with ".dat", therefore to find all matching names in /your/specified/path/ which contains many subdirectories, which could contain files that match this pattern:
$ find /your/specified/path/* -name "MAG_L_NT_*.dat"
However this prints all found filenames, but we still get names containing "SUM" string, there comes in grep. To exclude names containing unwanted string we will use option -v:
-v, --invert-match
Invert the sense of matching, to select non-matching lines. (-v is
specified by POSIX .)
To use grep to filter out first commands output we will use pipe () |:
The standard shell syntax for pipelines is to list multiple commands,
separated by vertical bars ("pipes" in common Unix verbiage). For
example, to list files in the current directory (ls), retain only the
lines of ls output containing the string "key" (grep), and view the
result in a scrolling page (less), a user types the following into the
command line of a terminal:
ls -l | grep key | less
"ls -l" produces a process, the output (stdout) of which is piped to
the input (stdin) of the process for "grep key"; and likewise for the
process for "less". Each process takes input from the previous process
and produces output for the next process via standard streams. Each
"|" tells the shell to connect the standard output of the command on
the left to the standard input of the command on the right by an
inter-process communication mechanism called an (anonymous) pipe,
implemented in the operating system. Pipes are unidirectional; data
flows through the pipeline from left to right.
process1 | process2 | process3
After you got acquainted to mentioned commands and options which will be used to achieve your goal, you are ready for solution:
$ find /your/specified/path/* -name "MAG_L_NT_*.dat" | grep -v "SUM"
This command will produce output of all names which begin "MAG_L_NT_" and end with ".dat". grep -v will use first command output as input and remove all lines containing "SUM" string.

Like a vlookup but in bash to match filenames in a directory against a ref file and return full description

I am aware there isn't a special bash function to do this and we will have to build this with available tools -- e.g. sed, awk, grep, etc.
We dump files into a directory and while their filename looks random, they can be mapped to their full description. For example:
/tmp/abcxyz.csv
/tmp/efgwaz.csv
/tmp/mnostu.csv
In filemapping.dat, we have:
abcxyz, customer_records_abcxyz
efgwaz, routernodes_logs_efgwaz
mnostu, products_campaign
We need to go through each of them in the directory recursively and rename the file with its full description. Final outcome:
/tmp/customer_records_abcxyz.csv
/tmp/routernodes_logs_efgwaz.csv
/tmp/products_campaign_mnostu.csv
I found something similar here but not sure how to work it out at directory level dealing with only one file as the lookup/referece file. Please help. Thanks!
I would try something like this:
sed 's/,/.csv/;s/$/.csv/' filemapping.dat | xargs -n2 mv
Either cd to tmp beforehand, or modify the sed command to include the path name.
The sed commands simply replace the comma and the line end with the string ".csv".

Gsutil wildcard search

I have to search 2 files from list of files.
The 2 Files which I have to search are in format googlea_1234_20151208.txt and googleb_7654_20151208.txt, so i am thinking of basing my search on keyword googlea , googleb and 20151208 .
Using gsutil, i can find individual files.
Using command gsutil ls gs://bucketid/*googlea_1234_20151208* which gives me first file and gsutil ls gs://bucketid/*googlea_1234_20151208* gives me 2nd file.
Looking for a command which will give me both files with one command
gsutil ls gs://bucketid/*google*20151208*
Assuming that gsutil is just passing the ls args to a real ls type processor, try
gsutil ls gs://bucketid/*google[ab]_*20151208*
The [ab] is know as a character-class. Rather than use ? to match any single character, [ab] says, match a single char if it is a or b
IHTH

List multiple directories contents and its path

I want to write a linux script or command that will:
Look into multiple specific directories and list its contents
For example
/test/dir1/abc/version1/program_name/
/test/dir1/abc/version2/program_name/
/test/dir1/abc/version3/program_name/
/test/dir1/bca/version1/program_name/
/test/dir1/bca/version2/program_name/
/test/dir1/bca/version3/program_name/
/test/dir1/cab/version1/program_name/
/test/dir1/cab/version2/program_name/
/test/dir1/cab/version3/program_name/
I can do a
ls -al /test/dir1/*/
and see its contents. But I just want to see what it inside version2 and version3.
for example
ls -al /test/dir1/*/<version2 or version3>/*
and get a list like:
/test/dir1/abc/version2/program_name/
/test/dir1/abc/version3/program_name/
/test/dir1/bca/version2/program_name/
/test/dir1/bca/version3/program_name/
/test/dir1/cab/version2/program_name/
/test/dir1/cab/version3/program_name/
Not including version1. There is more directories than version1, version2, and version3. Thats why just excluding version1 doesnt work.
Any help really appreciated!
You want to use two glob expansions for this search. Try this:
ls -al /test/dir1/*/version[23]/*
It will search through all of the /test/dir1/* directories, and then look for subdirectories matching either 'version2' or 'version3'.
You can use list feature (glob) in BASH:
ls -al /test/dir1/*/{version2,version3}/*

Resources