3

I need to gather a list of files and put this in a textfile. However, the files should not include their extension.

The command I have now without removing file extensions:

ls -1 /a/dir/*/dir/* > textfile

All selected files will have a an extension of .[a-z]{3}

(the reason I need this is because I need a list of unique base names, and unique will solve that after this step)

0

7 Answers 7

4

I always like to include a bash only solution:

for file in /a/dir/*/dir/*; do
    echo "${file%.*}" >> ~/file_list
done

and with an optional if statement to limit the file to your requested extension:

shopt -s extglob
for file in /a/dir/*/dir/*; do
    if [[ "$file" =~ \.[a-zA-Z]{3}$ ]]; then
        echo "${file%.*}" >> ~/file_list
    fi
done

In this similar serverfault question I explain the "${file%.*}" parameter expansion.

5

Something like that would list the file in the current directory removing everything after the first dot.

find . -maxdepth 1 -type f | xargs -iZ basename Z | cut -d"." -f1 > /tmp/resultfile

It would eventually have an issue with hidden files resulting in a blank line in the result file. Basename is here only to get rid of the "./" begining the filenames in the find result.

3

How about:

ls -1 /a/dir/*/dir/* | sed -e 's/\.[a-zA-Z0-9]\{3\}$//'

Should do what you want.

1
  • I disagree with the edit, but cannot reject as I don't have enough points. The original question explicitly states that the pattern being matched is .[a-z]{3}, so the edit to add [A-Z] is incorrect. Nov 25, 2015 at 12:37
2

It's much more simple than one thinks:

asd@locutus:~$ IZE=file.avi
asd@locutus:~$ echo $IZE
file.avi
asd@locutus:~$ echo ${IZE%%.???}
file
asd@locutus:~$ 

So in this manner:

ls -1 /a/dir/*/dir/* | while read VAR; do echo ${VAR%.???}; done

You can do whatever you want between do and done, echo is just an example.

man bash (Parameter Expansion):

   ${parameter%%word}
          The word is expanded to produce a pattern just as in pathname  expansion.
          If the pattern matches a trailing portion of the expanded value of param‐
          eter, then the result of the expansion is the expanded value of parameter
          with the shortest matching pattern (the ‘‘%’’ case) or the longest match‐
          ing pattern (the ‘‘%%’’ case) deleted.  If parameter is @ or *, the  pat‐
          tern  removal  operation is applied to each positional parameter in turn,
          and the expansion is the resultant list.  If parameter is an array  vari‐
          able subscripted with @ or *, the pattern removal operation is applied to
          each member of the array in turn, and  the  expansion  is  the  resultant
          list.

1

A more generic answer, finds extensions of any length:

find . -type f | sed 's/^.*\.\([^.]*\)$/\1/'

I then use the following command to get a list of extensions in a dir:

find . -type f | sed 's/^.*\.\([^.]*\)$/\1/' | sort | uniq -c | sort -n
1

You can also use cut like this :

for file in /a/dir/*/dir/* ; do
  echo \`echo $file | cut -d"." -f 1` >> textfile;
done

It will only work if you don't have any file or directories with a "." in the name

0

You have given an explicit definition for extensions,
But, the tags linux and bash-scripting suggest a unix environment.
Unless you are doing this with Cygwin on Windows.
These points may not matter in that case...

  • Be sure that you do not have numbers in your 'extension' (like md5)
  • Also, what about extensions with less than 3 characters? (script.sh)
  • What about extensions with upper case characters?
2
  • I match with my ls very specific files, a base name plus 4x an extension of 3 lowercase characters
    – Peter Smit
    Jul 30, 2009 at 11:57
  • @Peter, in which case, Russell's answer would have sufficed. ok.
    – nik
    Jul 30, 2009 at 16:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .