How to get a list of the filenames of a specific folder in shell script? - linux

I am trying to get all the filenames of a specific folder in a text file and I want only the names, not the relative path. I tried:
ls -1 a/b/c>filenames.txt
and its output is
file-2021-08-18.txt
file2-2021-08-18.js
file3-2021-08-18.json
file4-2021-08-19.json
which is what I want but only a specific day's file.
But when I do this:
ls -1 a/b/c/*2021-08-18*>filenames.txt
then the output is
a/b/c/file-2021-08-18.txt
a/b/c/file2-2021-08-18.js
a/b/c/file3-2021-08-18.json
I want only the filenames not the path of the files.
So, required output:
file-2021-08-18.txt
file2-2021-08-18.js
file3-2021-08-18.json
Is there any straightforward solution for this? OR I need to trim the output.
Thanks!!

When the argument to ls is a directory, it lists the filenames in the directory.
But when you use a wildcard, the shell expands the wildcard to all the filenames. So ls doesn't receive the directory as its argument, it receives all the filenames, and it lists them as given.
You can change to the directory and then list the matching files in the current directory:
(cd /a/b/c; ls *2021-08-18*) > filenames.txt
The parentheses make this run in a subshell, so the working directory of the original shell is unaffected.

With GNU find you may use the -printf option:
find a/b/c/ -type f -name "*2021-08-18*" -printf "%f\n" > filenames.txt
The directive %f picks out the file's name with any leading directories removed. Since -printf doesn't add a newline (\n) after the filename, we add one in order to match the required output.

Related

How to loop through subdirectories in a bash script?

Suppose I'm in a directory, dir1. Within that directory I have myscript.sh and a directory subdir1. subdir1 has several subsub directories, subsub1, subsub2, subsub3. Within each of those subsub directories is a bash script all named script2.sh, and I want to run each one of them.
First, I just want to make sure I can print all the subsub directories.
I have:
for dir in /subdir1/*/ ; do
echo $dir
done
Can anyone tell me what I'm doing wrong?
I guess you could run them this way:
find subdir1 -type f -name "NAME_OF_YOUR_SCRIPT.sh" -exec {} \;
You are going to run into issues if any of the directories have spaces or other special characters in the names.
Based on what you provided
for scriptfile in ./subdir/*/*script2.sh
do
/bin/sh $scriptfile
done
may work best for you.
To deal with spaces or other special characters in your directory names, you'll want to use find and pass the output to xargs.

Linux terminal: Recursive search for string only in files w given file extension; display file name and absolute path

I'm new to Linux terminal; using Ubuntu Peppermint 5.
I want to recursively search all directories for a given text string (eg 'mystring'), in all files which have a given file extension (eg. '*.doc') in the file name; and then display a list of the file names and absolute file paths of all matches. I don't need to see any lines of content.
This must be a common problem. I'm hoping to find a solution which does the search quickly and efficiently, and is also simple to remember and type into the terminal.
I've tried using 'cat', 'grep', 'find', and 'locate' with various options, and piped together in different combinations, but I haven't found a way to do the above.
Something similar was discussed on:
How to show grep result with complete path or file name
and:
Recursively search for files of a given name, and find instances of a particular phrase AND display the path to that file
but I can't figure a way to adapt these to do the above, and would be grateful for any suggestions.
According to the grep manual, you can do this using the --include option (combined with the -l option if you want only the name — I usually use -n to show line numbers):
--include=glob
Search only files whose name matches glob, using wildcard matching as described under --exclude.
-l
--files-with-matches
Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning of each file stops on the first match. (-l is specified by POSIX.)
A suitable glob would be "*.doc" (ensure that it is quoted, to allow the shell to pass it to grep).
GNU grep also has a recursive option -r (not in POSIX grep). Together with the globbing, you can search a directory-tree of ".doc" files like this:
grep -r -l --include="*.doc" "mystring" .
If you wanted to make this portable, then find is the place to start. But using grep's extension makes searches much faster, and is available on any Linux platform.
find . -name '*.doc' -exec grep -l 'mystring' {} \; -print
How it works:
find searches recursively from the given path .
for all files which name is '*.doc'
-exec grep execute grep on files found
suppress output from grep -l
and search inside the files for 'mystring'
The expression for grep ends with the {} \;
and -print print out all names where grep founds mystring.
EDIT:
To get only results from the current directory without recursion you can add:
-maxdepth 0 to find.

Linux: how to rename all files in a directory to uppercase? [duplicate]

This question already has answers here:
How do I rename all folders and files to lowercase on Linux?
(30 answers)
Closed 7 years ago.
Including the extension. Eg file.txt --> FILE.TXT
If anyone could point me in the general direction then I'd be grateful :)
And here is just some random text because the character count was too low for Stackoverflow...
An initial solution would be:
rename 'y/a-z/A-Z/' *
It takes every file/directory in current directory, and changes every character in the range a-z by its corresponding uppercase version.
The problem with rename is there is no option to go inside directories to apply the renaming recursively, and * character is expanded to names of current directory (files and directories). Even more, this command will rename directories also, but you only want to rename files.
To do it recursively, but over files only, you can use find, which search recursively, and pass each file to rename:
find . -type f -execdir rename 'y/a-z/A-Z/' {} \;
This command searches only files, and executes rename over each file inside the directory (execdir option) where that file has been found. That's important because otherwise find will pass the complete path of the file (eg: ./fold1/fold2/file.txt') to rename, which in turns will try to pass to uppercase the complete path: (./FOLD1/FOLD2/FILE.TXT) which will cause an error because folders FOLD1 and FOLD2 don't exist.
Using bash, this is easy:
for f in *; do mv "$f" "${f^^}"; done
The expansion ${f^^} converts the name of the file to uppercase.
In another shell, using tr:
for f in *; do mv "$f" "$(echo "$f" | tr '[:lower:]' '[:upper:]')"; done
I would suggest something like that:
ls|sed 's/\(.*\)/mv "\1" "\U\1"/' | sh
I like to use sed this way, because it is easy to inspect the output before piping it into sh (removing |sh in a first step)
Using perl
perl -e 'for (glob "*.txt" ){ rename $_,uc($_)}'
glob "*" creates a list of all the .txt files in the current directory.
rename replaces each value with a uc (uppercase) value.

How can i get the last word of a string linux

For example:
im in this directory, for example, "home/linux/downloads/dir1" and I want to show the files in another directory.
I use: find /home/linux/files/
This command shows the files of the previous path like this:
/home/linux/files/file1.txt
/home/linux/files/file2.txt
using cut -d "/" -f4 i get file1.txt but if you change the path, this command no longer serves me.
There is a command that allows me to always get the last word of a string separated by /?
basename is what you want, because you're asking about paths. In Python it's os.path.basename().
You can use find's -exec for this:
find <directory> -exec basename {} \;
This will work in any directory. -exec tells find to execute the command for every file found. Here the command is basename, which returns only the file name without directory prefixes. Hope it helps.
Something like this:
path = '/home/linux/files/dir1'
lastdir = path.split('/')[-1]
yields 'dir1'

How to recursive list files with size and last modified time?

Given a directory i'm looking for a bash one-liner to get a recursive list of all files with their size and modified time tab separated for easy parsing. Something like:
cows/betsy 145700 2011-03-02 08:27
horses/silver 109895 2011-06-04 17:43
You can use stat(1) to get the information you want, if you don't want the full ls -l output, and you can use find(1) to get a recursive directory listing. Combining them into one line, you could do this:
# Find all regular files under the current directory and print out their
# filenames, sizes, and last modified times
find . -type f -exec stat -f '%N %z %Sm' '{}' +
If you want to make the output more parseable, you can use %m instead of %Sm to get the last modified time as a time_t instead of as a human-readable date.
find is perfect for recursively searching through directories. The -ls action tells it to output its results in ls -l format:
find /dir/ -ls
On Linux machines you can print customized output using the -printf action:
find /dir/ -printf '%p\t%s\t%t\n'
See man find for full details on the format specifiers available with -printf. (This is not POSIX-compatible and may not be available on other UNIX flavors.)
find * -type f -printf '%p\t%s\t%TY-%Tm-%Td %Tk:%TM\n'
If you prefer fixed-width fields rather than tabs, you can do things like changing %s to %10s.
I used find * ... to avoid the leading "./" on each file name. If you don't mind that, use . rather than * (which also shows files whose names start with .). You can also pipe the output through sed 's/^\.\///'.
Note that the output order will be arbitrary. Pipe through sort if you want an ordered listing.
You could try this for recursive listing from current folder called "/from_dir"
find /from_dir/* -print0 | xargs -0 stat -c “%n|%A|%a|%U|%G” > permissions_list.txt

Lists files and directories passes through to stat command and puts all the info into a file called permissions_list.txt
“%n|%A|%a|%U|%G” will give you the following result in the file:
from_
 dir|drwxr-sr-x|2755|root|root
from_dir/filename|-rw-r–r–|644|root|root

Cheers!


Resources