How about using the proper path handling methods from os.path?
>>> f = 'C:\\X\\Data\\foo.txt'
>>> import os
>>> os.path.basename(f)
'foo.txt'
>>> os.path.dirname(f)
'C:\\X\\Data'
>>> os.path.splitext(f)
('C:\\X\\Data\\foo', '.txt')
>>> os.path.splitext(os.path.basename(f))
('foo', '.txt')
Answer from Martlark on Stack OverflowHow about using the proper path handling methods from os.path?
>>> f = 'C:\\X\\Data\\foo.txt'
>>> import os
>>> os.path.basename(f)
'foo.txt'
>>> os.path.dirname(f)
'C:\\X\\Data'
>>> os.path.splitext(f)
('C:\\X\\Data\\foo', '.txt')
>>> os.path.splitext(os.path.basename(f))
('foo', '.txt')
simple Example for your Help.
import os
from os import path
path_to_directory = "C:\\X\\Data"
for f in os.listdir(path_to_directory):
name , extension = path.splitext(f)
print(name)
Output
foo
bar
The following should work for you
s="Planning_Group_20180108.ind"
'_'.join(s.split('_')[:-1])
This way you create a list which is the string split at the _. With the [:-1] you remove the last part. '_'.join() combines your list elements in the resulting list.
First I would extract filename itself. I'd split it from the extension. You can go easy way by doing:
path = "Planning_Group_20180108.ind"
filename, ext = path.split(".")
It is assuming that path is actually only a filename and extension. If I'd want to stay safe and platform independent, I'd use os module for that:
fullpath = "this/could/be/a/full/path/Planning_Group_20180108.ind"
path, filename = os.path.split(fullpath)
And then extract "root" and extension:
root, ext = os.path.splitext(filename)
That should leave me with Planning_Group_20180108 as root. To discard "_20180108" we need to split string by "_" delimiter, going from the right end, and do it only once. I would use .rsplit() method of string, which lets me specify delimiter, and number of times I want to make splits.
what_i_want, the_rest = root.rsplit("_", 1)
what_i_want should contain left side of Planning_Group_20180108 cut in place of first "_" counting from right side, so it should be Planning_Group
The more compact way of writing the same, but not that easy to read, would be:
what_i_want = os.path.splitext(os.path.split("/my/path/to/Planning_Group_20180108.ind")[1])[0].rsplit("_", 1)
PS. You may skip the part with extracting root and extension if you're sure, that extension will not contain underscore. If you're unsure of that, this step will be necessary. Also you need to think of case with multiple extensions, like /path/to/file/which_has_a.lot.of.periods.and_extentions. In that case would you like to get which_has_a.lot.of.periods.and, or which_has? Think of it while planning your app. If you need latter, you may want to extract root by doing filename.split(".", 1) instead of using os.path.splitext()
reference:
os.path.split(path),
os.path.splitext(path)
str.rsplit(sep=None, maxsplit=-1)
splitting filenames names on underscore
Split a string by a delimiter in Python - Stack Overflow
Splitting filenames for their first word in Python - Geographic Information Systems Stack Exchange
python - split a file name - Stack Overflow
I have a bunch of files in a zip file with the following format a_b_c.ext what i want is for the code to do two things. First is to check for a certain type of extension. Second is to split the file names at the first '_' and only keep the string before the first underscore. I know how to do the former but not the latter. So far I have something like this
import os
from zipfile import ZipFile
with ZipFile('foo.zip', 'r') as f:
filenames = f.namelist()
for line in filenames:
if line.endswith('.foo') or line.endswith('.foo2'):
sep = '_'
rest_of_string = line.split(sep,1)[0]
print(rest_of_string)
This gives me foldername/part of file name I want. How do I get it to return just part of file name I want?
Use the str.split method:
Use with AI>>> "MATCHES__STRING".split("__")
['MATCHES', 'STRING']
Besides split and rsplit, there is partition/rpartition. It separates string once, but the way question was asked, it may apply as well.
Example:
Use with AI>>> "MATCHES__STRING".partition("__")
('MATCHES', '__', 'STRING')
>>> "MATCHES__STRING".partition("__")[::2]
('MATCHES', 'STRING')
And a bit faster then split("_",1):
Use with AI$ python -m timeit "'validate_field_name'.split('_', 1)[-1]"
2000000 loops, best of 5: 136 nsec per loop
$ python -m timeit "'validate_field_name'.partition('_')[-1]"
2000000 loops, best of 5: 108 nsec per loop
Timeit lines are based on this answer
fn = "LN0001_07272010_3.dat".split('_')
new_fn = '{0}_JY_{1}'.format(fn[0], fn[1])
Update forgot to add "JY" to new_fn
filename="LN0001_07272010_3.dat"
newfilename=filename.split("_")[0]+"_JY_"+filename.split("_")[1]
linearr=[]
for line in open(filename).readlines():
linearr.append(line+"|")
f=open(newfilename, "w")
for line in linearr:
f.write(line)
f.close()
You could use itertools.groupby to group lines that occur after :Entry into lists:
import itertools as it
filename='test.dat'
with open(filename,'r') as f:
for key,group in it.groupby(f,lambda line: line.startswith(':Entry')):
if not key:
group = list(group)
print(group)
yields
['- Name\n', 'John Doe\n', '\n', '- Date\n', '20/12/1979\n']
['\n', '-Name\n', 'Jane Doe\n', '- Date\n', '21/12/1979\n']
Or, to process the groups, you don't really need to convert group to a list:
with open(filename,'r') as f:
for key,group in it.groupby(f,lambda line: line.startswith(':Entry')):
if not key:
for line in group:
...
If every entry block starts with a colon, you can just split by that:
with open('entries.txt') as fp:
contents = fp.read()
for entry in contents.split(':'):
# do something with entry
A one liner, no programming. (except the regexp etc.)
csplit --digits=2 --quiet --prefix=outfile infile "/-|/+1" "{*}"
tested on:
csplit (GNU coreutils) 8.30
Notes about usage on Apple Mac
"For OS X users, note that the version of csplit that comes with the OS doesn't work. You'll want the version in coreutils (installable via Homebrew), which is called gcsplit." — @Danial
"Just to add, you can get the version for OS X to work (at least with High Sierra). You just need to tweak the args a bit csplit -k -f=outfile infile "/-\|/+1" "{3}". Features that don't seem to work are the "{*}", I had to be specific on the number of separators, and needed to add -k to avoid it deleting all outfiles if it can't find a final separator. Also if you want --digits, you need to use -n instead." — @Pebbl
awk '{f="file" NR; print $0 " -|"> f}' RS='-\\|' input-file
Explanation (edited):
RS is the record separator, and this solution uses a gnu awk extension which allows it to be more than one character. NR is the record number.
The print statement prints a record followed by " -|" into a file that contains the record number in its name.
if you just want the name of the file to be split based on "_", if filename = "animal_cat_kowai.png"
your_list = filename[:filename.index(".")].split("_")
This would result in your_lisr = ["animal","cat","kowai"]
I think that list is not suitable for the link. Insted, use dict.
First import required modules.
from pathlib import Path
Initiate variable.
image_dict = {} # handle name and link
all_file = list(Path().iterdir()) # get all file in current directory
Populate image_dict.
for f in all_file:
extension = str(f).split(".")[-1]
filename = str(f).split("." + extension)[0]
if extension in ["png", "jpeg"]: # In case of there is other file that's no an image
part_name = filename.split("_") # Get keywords from filename
for pn in part_name: # Append a link from each keyword
if image_dict.get(pn, None) is not None:
image_dict[pn].append(f.resolve())
else:
image_dict[pn] = [f.resolve()]
print(image_dict) # This is the result