Extract file basename without path and extension in bash
You don't have to call the external basename
command. Instead, you could use the following commands:
$ s=/the/path/foo.txt
$ echo "${s##*/}"
foo.txt
$ s=${s##*/}
$ echo "${s%.txt}"
foo
$ echo "${s%.*}"
foo
Note that this solution should work in all recent (post 2004) POSIX compliant shells, (e.g. bash
, dash
, ksh
, etc.).
Source: Shell Command Language 2.6.2 Parameter Expansion
More on bash String Manipulations: http://tldp.org/LDP/LG/issue18/bash.html
Extract filename and extension in Bash
First, get file name without the path:
filename=$(basename -- "$fullfile")
extension="${filename##*.}"
filename="${filename%.*}"
Alternatively, you can focus on the last '/' of the path instead of the '.' which should work even if you have unpredictable file extensions:
filename="${fullfile##*/}"
You may want to check the documentation :
- On the web at section "3.5.3 Shell Parameter Expansion"
- In the bash manpage at section called "Parameter Expansion"
How can I remove the extension of a filename in a shell script?
You should be using the command substitution syntax $(command)
when you want to execute a command in script/command.
So your line would be
name=$(echo "$filename" | cut -f 1 -d '.')
Code explanation:
echo
get the value of the variable$filename
and send it to standard output- We then grab the output and pipe it to the
cut
command - The
cut
will use the . as delimiter (also known as separator) for cutting the string into segments and by-f
we select which segment we want to have in output - Then the
$()
command substitution will get the output and return its value - The returned value will be assigned to the variable named
name
Note that this gives the portion of the variable up to the first period .
:
$ filename=hello.world
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello.hello.hello
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello
$ echo "$filename" | cut -f 1 -d '.'
hello
How can I extract the filename without extension (and add a counter) from a variable on the Linux command line?
$ ls *.jpg
DSCa_.jpg* DSCb_.jpg* DSCc_.jpg*
$ count=0; for file in *.jpg; do (( count++ )); convert -resize 25% "$file" "${file%\.*}$count.png"; done
$ ls *.png
DSCa_1.png DSCb_2.png DSCc_3.png
${file%\.*}
uses parameter substitution to remove the shortest matching string from the right of $file
. You can read more about parameter substitution here
How do I remove the file suffix and path portion from a path string in Bash?
Here's how to do it with the # and % operators in Bash.
$ x="/foo/fizzbuzz.bar"
$ y=${x%.bar}
$ echo ${y##*/}
fizzbuzz
${x%.bar}
could also be ${x%.*}
to remove everything after a dot or ${x%%.*}
to remove everything after the first dot.
Example:
$ x="/foo/fizzbuzz.bar.quux"
$ y=${x%.*}
$ echo $y
/foo/fizzbuzz.bar
$ y=${x%%.*}
$ echo $y
/foo/fizzbuzz
Documentation can be found in the Bash manual. Look for ${parameter%word}
and ${parameter%%word}
trailing portion matching section.
Bash extracting file basename from long path
It's better to use an array to hold the filenames. A string variable will not handle filenames which contain spaces.
Also, you don't need to use the basename
command. Instead use bash's built-in string manipulation.
Try this:
files=( /very/long/path/to/various/files/*.file )
for file in "${files[@]}"
do
filename="${file##*/}"
filenameWithoutExtension="${filename%.*}"
echo "$filenameWithoutExtension"
done
Using 'find' to return filenames without extension
To return only filenames without the extension, try:
find . -type f -iname "*.ipynb" -execdir sh -c 'printf "%s\n" "${0%.*}"' {} ';'
or (omitting -type f
from now on):
find "$PWD" -iname "*.ipynb" -execdir basename {} .ipynb ';'
or:
find . -iname "*.ipynb" -exec basename {} .ipynb ';'
or:
find . -iname "*.ipynb" | sed "s/.*\///; s/\.ipynb//"
however invoking basename
on each file can be inefficient, so @CharlesDuffy suggestion is:
find . -iname '*.ipynb' -exec bash -c 'printf "%s\n" "${@%.*}"' _ {} +
or:
find . -iname '*.ipynb' -execdir basename -s '.sh' {} +
Using +
means that we're passing multiple files to each bash instance, so if the whole list fits into a single command line, we call bash only once.
To print full path and filename (without extension) in the same line, try:
find . -iname "*.ipynb" -exec sh -c 'printf "%s\n" "${0%.*}"' {} ';'
or:
find "$PWD" -iname "*.ipynb" -print | grep -o "[^\.]\+"
To print full path and filename on separate lines:
find "$PWD" -iname "*.ipynb" -exec dirname "{}" ';' -exec basename "{}" .ipynb ';'
Extract directory path and filename
Use the basename command to extract the filename from the path:
[/tmp]$ export fspec=/exp/home1/abc.txt
[/tmp]$ fname=`basename $fspec`
[/tmp]$ echo $fname
abc.txt
Get extension of files in Bash
It seems that you are only asking how to put the file extension of a filename into a variable in bash, and you are not asking about the sorting part.
To do so, the following brief script can print the extension of each file from a file list.
#!/bin/sh
filesInCurrentDir=`ls`
for file in $filesInCurrentDir; do
extention=`sed 's/^\w\+.//' <<< "$file"`
echo "the extention for $file is: "$extention #for debugging
done
the variable that contains the extention of the current file analysed is called extention
. The command sed 's/^\w\+.//
matched any length of characters until the first dot found in the filename and then removes it. Therefore if there are multiple file extentions these would be all listed (e.g. file.txt
-> get extention txt
but file.odt.pdf
-> get extention odt.pdf
).
EXAMPLE
Current Folder content (this can be any space-separated list of files that you feed to the loop)
aaab.png
abra
anme2.jpg
cadabra
file
file.png
file.txt
loacker.png
myText
name.pdf
rusty.jgp
Result of script above:
the extention of aaab.png is: png
the extention of abra is:
the extention of anme2.jpg is: jpg
the extention of cadabra is:
the extention of file is:
the extention of file.png is: png
the extention of file.txt is: txt
the extention of loacker.png is: png
the extention of myText is:
the extention of name.pdf is: pdf
the extention of rusty.jgp is: jgp
In this way, files with no extension will result in the extension variable being empty.
Related Topics
Connection Refused to Mongodb Errno 111
Using the "Alternate Screen" in a Bash Script
How to Use Grep to Show Just Filenames on Linux
Spring Boot Application as a Service
Contiguous Physical Memory from Userspace
How to Programmatically "Burn In" Ansi Control Codes to a File Using Unix Utils
How to Pipe Initial Input into Process Which Will Then Be Interactive
Linux Clock_Gettime(Clock_Monotonic) Strange Non-Monotonic Behavior
Is There Really No Asynchronous Block I/O on Linux
How to Use Debug Version of Libc
The Bash Command :(){ :|:& };: Will Spawn Processes to Kernel Death. Can You Explain the Syntax
How to Only Get File Name With Linux 'Find'
Find -Exec' a Shell Function in Linux
What's the Difference Between "Statically Linked" and "Not a Dynamic Executable" from Linux Ldd
How to Add Users to Docker Container
Managing Log Files Created by Cron Jobs