3

I'd like to move a file from one directory to another by filtering the filename with a specific string

Seems like fnmatch or glob can do this but I can't figure it out

In the example below, how could python move only the file test_High_Quality.mb to another directory using the filter High_Quality in the filename

>>> import os    
>>> myPath = "C:\Project"    
>>> os.listdir('myPath')    
>>> ['test_Draft.txt', 'test_Mid_Quality.txt', 'test_High_Quality.txt']
Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
ADMMTL
  • 43
  • 1
  • 3

6 Answers6

3

To filter with file names "High_Quality"

[d for d in os.listdir('myPath') if 'High_Quality' in d]

For moving to other directory, follow this solution similar question

Community
  • 1
  • 1
manvi77
  • 536
  • 1
  • 5
  • 15
1

You could use the glob.glob() function to search for filenames matching patterns.

> from glob import glob
> glob("C:\Project\*High_Quality*")

['test_High_Quality.txt']

See the linked documentation for further details.

salezica
  • 74,081
  • 25
  • 105
  • 166
  • This is what I get when I try the code above: ['C:/Project\\test_High_Quality.txt']. May be the '\\' could cause a problem, no? – ADMMTL Mar 14 '17 at 16:30
1

Another approach using filter:

high_quality = filter(lambda fname: 'High_Quality' in fname, os.listdir('myPath'))

Convert high_quality to a list or set if you want to iterate over it more than once (filter returns a generator).

blacksite
  • 12,086
  • 10
  • 64
  • 109
  • I'll study to understand what is happening in this line of code as I'm not familiar with the lambda function. This is going to be very useful for my script. Thanks a lot – ADMMTL Mar 14 '17 at 16:34
1

You can use filter method from fnmatch module for the same purpose, very straightforward application, just make sure you build the correct pattern to your needs, like in your case matching all string including High_Quality :

>>> l = ['test_Draft.txt', 'test_Mid_Quality.txt', 'test_High_Quality.txt']
>>> 
>>> import fnmatch
>>> 
>>> fnmatch.filter(l, "*High_Quality*")
['test_High_Quality.txt']
Iron Fist
  • 10,739
  • 2
  • 18
  • 34
  • I didn't think to store all the filenames in a list before applying a filter. Very good trick. Thank you very much – ADMMTL Mar 14 '17 at 16:43
  • @ADMMTL, There is no trick about this solution, except for using elementary programming technique with Python, you seem to be very new, it will become common-sense to you after practicing more with this language :) – Iron Fist Mar 14 '17 at 16:49
0

If you stick this file in an empty directory you can see how glob will work just fine for you. You just need *High_Quality* as your glob pattern:

from __future__ import print_function

import glob
import os


filenames = [
    'fnord.txt',
    'fizzy.txt',
    'test_Low_Quality.txt',
    'test_Mid_Quality.txt',
    'test_High_Quality.txt',
    'test_High_Quality_one.txt',
    'test_High_Quality_two.txt',
]

for filename in filenames:
    with open(filename, 'w'): pass
print('Files:')
print('\t', '\n\t'.join(os.listdir(os.curdir)), sep='')
print('Files matching *High_Quality*:')
print('\t', '\n\t'.join(glob.glob('*High_Quality*')), sep='')
Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
  • This script is a little bit advanced for my skills but I'll study it very carefully. Thank you very much for your help – ADMMTL Mar 14 '17 at 16:44
0

Filter with glob module:

Import glob

import glob

Pattern

pattern='*High_Quality*'

files=glob.glob(pattern)

Wild Cards:

files=glob.glob("data/*")

print(files)


Out:

['data/ks_10000_0', 'data/ks_1000_0', 'data/ks_100_0', 'data/ks_100_1',
'data/ks_100_2', 'data/ks_106_0', 'data/ks_19_0', 'data/ks_200_0', 'data/ks_200_1', 
'data/ks_300_0', 'data/ks_30_0', 'data/ks_400_0', 'data/ks_40_0', 'data/ks_45_0', 
'data/ks_4_0', 'data/ks_500_0', 'data/ks_50_0', 'data/ks_50_1', 'data/ks_60_0', 
'data/ks_82_0', 'data/ks_lecture_dp_1', 'data/ks_lecture_dp_2']

Fiter extension .txt:

files = glob.glob("/home/ach/*/*.txt")

A single character

glob.glob("/home/ach/file?.txt")

Number Ranges

glob.glob("/home/ach/*[0-9]*")

Alphabet Ranges

glob.glob("/home/ach/[a-c]*")
Community
  • 1
  • 1
pink.slash
  • 1,817
  • 15
  • 14