I want to extract all image names with sub folder names into a CSV file.

I have this folder structure

Desktop/Wall Arts Product Images/framed-posters/landscape/animals-and-birds/Bighorn/Bighorn.jpg
Desktop/Wall Arts Product Images/framed-posters/landscape/animals-and-birds/Lion/Lion.jpg
Desktop/Wall Arts Product Images/framed-posters/landscape/animals-and-birds/Giant-Panda/Giant-Panda.jpg
Desktop/Wall Arts Product Images/posters/landscape/Automobiles/Best-Deisgner-Jack-Daniel-Chopper/Best-Deisgner-Jack-Daniel-Chopper.jpg
Desktop/Wall Arts Product Images/posters/landscape/Automobiles/Ford-Mustang-Cars-Classic/Ford-Mustang-Cars-Classic.jpg
Desktop/Wall Arts Product Images/framed-posters/potrait/gods/Mukkunda/Mukkunda.jpg

and many more.

I run this command but it gives only folder name posters and framed-posters

'ls' | sed -e 's/^/"/' -e 's/$/"/' > files.csv

The desired output is like -->

    Image name,category,subcategory,type

    Bighorn,landscape,animals and birds,framed-posters
    Lion,landscape,animals and birds,framed-posters
    Giant-Panda,landscape,animals and birds,framed-posters

How can I get the desired output in CSV file format?

4 Answers 4


Just because we can, here's a way that uses sed to reverse the order of the fields:

find -name "*.jpg" | sed -rn 's|^.||; s|[^/]*.jpg||; :a h; s|.*/(.*)|\1|p; x; s|(.*)/.*|\1| ; ta' | tr '\n' ',' | sed 's/,,/\n/g ; s/,$/\n/; s/^,//'

Yeah I know O_O

But it works even if the directory structure is not consistent

Here it is more readably with comments:

find -name "*.jpg" | sed -rn '{    #get the files and pipe the output to sed
s|^.||                             #remove the leading .
s|[^/]*.jpg||                      #and the basename, since each image is in a directory of the same name
:a h                               #create a label a for this branch and put the lines into the hold space in their current state
s|.*/(.*)|\1|p                     #print only the last field
x                                  #switch the hold space and pattern space 
s|(.*)/.*|\1|                      #exclude the last field from the new pattern space, which won't do anything if there is only one field on each line
ta                                 #if the last s command did anything, then start again from the label (:a) (thus recursively going through the fields and printing them out on separate lines in reverse order)
}' | tr '\n' ',' | sed '{          # finally turn the newlines into commas, then clean up the mess
s/,,/\n/g ; s/,$/\n/; s/^,//

Try with this:

find ~/Desktop -iname "*.jpg" -exec ls {} + | awk -F'/' ' BEGIN { OFS=", "; print "Image Name", "Category", "Subcategory", "type"} { print $(NF-1),$4, $5, $3 "" }' 

If you want to remove special character from image name, make use of below code:

find ~/Desktop -iname "*.jpg" -exec rename 's/[^a-zA-Z0-9.\/-]//g' {} +

Tweak it as per the output.

  • It is working fine .Only One issue it there.It is showing all ._African-Elephant-1.jpg African-Elephant-1.jpg ._African-Elephant-2.jpg African-Elephant-2.jpg ._African-Elephant-3.jpg African-Elephant-3.jpg ._African-Elephant-4.jpg African-Elephant-4.jpg ._African-Elephant-5.jpg African-Elephant-5.jpg like this .I want only name "African-Elephant" one time
    – Urvashi
    Feb 8, 2017 at 8:01
  • @Urvashi made changes to the script, try it out.
    – Rakesh.N
    Feb 8, 2017 at 8:06
  • @Urvashi No problem, If helped upvote it and mark it as answered.
    – Rakesh.N
    Feb 8, 2017 at 10:02
  • Done.I want one more help.I want to rename all images name which hhave special character.Then remove special character from image name .For Example image name is :Holy-#%@!-You-Are-40-Black then it should remove all special character and the new image name should be "Holy-You-Are-40-Black".I have code like sed "s/[!@#\$%^&*()\']//g" <<< "image name"
    – Urvashi
    Feb 9, 2017 at 6:24
  • @Urvashi made changes to answer, check it out.
    – Rakesh.N
    Feb 9, 2017 at 9:03

try this command..

find . | awk -F/ '{print $(NF-1)","$(NF-3)","$(NF-2)","$(NF-4)}'

Assuming you have a consistent directory tree structure, the python script presented below will traverse the directory tree and output csv contents to stdout stream ( use > operator on command-line to output contents into new file, as in ./dir_tree_csv.py > output_file.csv ). It is to be placed into Wall Arts Product Images directory and executed from there.

#!/usr/bin/env python
from __future__ import print_function
import os,sys

def get_all_files(treeroot):
    file_list = []
    for dir,subdirs,files in os.walk(treeroot):
         for f in files: 
             if os.path.basename(__file__) in f: continue
    return file_list

def main():
    if len(sys.argv) == 2: top_dir=sys.argv[1]
    files = get_all_files(top_dir)

    print("Image name,category,subcategory,type\n")

    for f in files:
        fields = f.split('/')
        fields[2],fields[3] = fields[3],fields[2]

if __name__ == '__main__' : main()

Test run:

# Replicated directory structure with only two of the files for simplicity
 $ tree
├── dir_tree_csv.py
├── framed-posters
│   └── landscape
│       └── animals-and-birds
│           └── Bighorn
│               └── Bighorn.jpg
└── posters
    └── landscape
        └── Automobiles
            └── Best-Deisgner-Jack-Daniel-Chopper
                └── Best-Deisgner-Jack-Daniel-Chopper.jpg

8 directories, 3 files
$ ./dir_tree_csv.py                                                                                   
Image name,category,subcategory,type


You must log in to answer this question.

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