How to extract a specific war file to a specific folder - python

I have the python code which will download the .war file and put it in a path which is specified by the variable path.
Now I wish to extract a specific file from that war to a specific folder.
But I got struck up here :
os.system(jar -xvf /*how to give the path varible here*/ js/pay.js)
I'm not sure how to pass on the variable path to os.system command.
I'm very new to python, kindly help me out.

If you really want to use os.system, the shell command line is passed as a string, and you can pass any string you want. So:
os.system('jar -xvf "' + pathvariable + '" js/pay.js)
Or you can use {} or %s formatting, etc.
However, you probably do not want to use os.system.
First, if you want to run other programs, it's almost always better to use the subprocess module. For example:
subprocess.check_call(['jar', '-xvf', pathvariable, 'js/pay.js'])
As you can see, you can pass a list of arguments instead of trying to work out how to put a string together (and deal with escaping and quoting and all that mess). And there are lots of other advantages, mostly described in the documentation itself.
However, you probably don't want to run the war tool at all. As jimhark says, a WAR file is just a special kind of JAR file, which is just a special kind of ZIP file. For creating them, you generally want to use JAR/WAR-specific tools (you need to verify the layout, make sure the manifest is the first entry in the ZIP directory, take care of the package signature, etc.), but for expanding them, any ZIP tool will work. And Python has ZIP support built in. What you want to do is probably as simple as this:
import zipfile
with zipfile.ZipFile(pathvariable, 'r') as zf:
zf.extract('js/pay.js', destinationpathvariable)
IIRC, you can only directly use ZipFile in a with statement in 2.7 and 3.2+, so if you're on, say, 2.6 or 3.1, you have to do it indirectly:
from contextlib import closing
import zipfile
with closing(zipfile.ZipFile(pathvariable, 'r')) as zf:
zf.extract('js/pay.js', destinationpathvariable)
Or, if this is just a quick&dirty script that quits as soon as it's done, you can get away with:
import zipfile
zf = zipfile.ZipFile(pathvariable, 'r')
zf.extract('js/pay.js', destinationpathvariable)
But I try to always use with statements whenever possible, because it's a good habit to have.

Isn't a war file a type of zip file? Python has zipfile support (click link for docs page).

You can use os.environ, it holds all environment variables on it.
It is a dict, so you can just use it like:
pypath = os.environ['PYTHONPATH']
now if you mean it's a common python variable, just use it like:
var1 = 'pause'
os.system('#echo & %s' % var1)

Related

Is it able to create folders with Python?

I am writing a Pokemon game and I want to make folders to save different types of Pokemon, as well as other sorts of information, in. I want to use folders because it would be really messy if I were to save all my data into a single file.
Is it possible to create folders with a Python program? This would make it easier and cleaner for me when I try to import the Pokemon data from external websites.
You can use open with the a mode, which opens a file in append mode, and creates it if it does not exist:
my_file = open('file.txt', 'a')
# Optionally: write stuff to my_file, using my_file.write('stuff')
my_file.close()
You can run any command that you want with python by doing:
import os
os.popen("mkdir random_name") # This creates a directory called "random_name"
os.popen("touch rando_name.txt") # This creates a file called "random_name"
You can run any command that you would usually run in terminal inside the popen.
You can use the popen() command in both UNIX(Linux, macOS) as well as Windows OS.
You can learn more regarding this by taking a look in the python documentation.
https://docs.python.org/2/library/subprocess.html
If you'd like to create folders (or directories), you need os.mkdir:
import os
os.mkdir("folder_name")
To create some deep folders at once, use os.makedirs:
os.makedirs("path/to/something")
Then all that structure of three folders will be created.
Tutorialspoint has a short tutorial about os.mkdir.
You can use with statement like this:
with open('some_file_100.txt', 'a') as f:
pass
The above will just create an empty file, if you want to write something to the created file, you can try:
with open('some_file_100.txt', 'a') as f:
f.write('some text')
When you use with statement you do not need to close your files explicitly because they are closed autmatically at the end of the block.

How to loop through the list of .tar.gz files using linux command in python

Using python 2.7
I have a list of *.tat.gz files on a linux box. Using python, I want to loop through the files and extract those files in a different location, under their respective folders.
For example: if my file name is ~/TargetData/zip/1440198002317590001.tar.gz
then I want to untar and ungzip this file in a different location under its
respective folder name i.e. ~/TargetData/unzip/1440198002317590001.
I have written some code but I am not able to loop through the files. In a command line I am able to untar using $ tar -czf 1440198002317590001.tar.gz 1440198002317590001 command. But I want to be able to loop through the .tar.gz files. The code is mentioned below. Here, I’m not able to loop just the files Or print only the files. Can you please help?
import os
inF = []
inF = str(os.system('ls ~/TargetData/zip/*.tar.gz'))
#print(inF)
if inF is not None:
for files in inF[:-1]:
print files
"""
os.system('tar -czf files /unzip/files[:-7]')
# This is what i am expecting here files = "1440198002317590001.tar.gz" and files[:-7]= "1440198002317590001"
"""
Have you ever worked on this type of use case? Your help is greatly appreciated!! Thank you!
I think you misunderstood the meaning of os.system(), that will do the job, but its return value was not expected by you, it returns 0 for successful done, you can not directly assign its output to a variable. You may consider the module [subprocess], see doc here. However, I DO NOT recommend that way to list files (actually, it returns string instead of list, see doc find the detail by yourself).
The best way I think would be glob module, see doc here. Use glob.glob(pattern), you can put all files match the pattern in a list, then you can loop it easily.
Of course, if you are familiar with os module, you also can use os.listdir(), os.path.join(), or even os.paht.expanduser() to do this. (Unlike glob, it only put filenames without fully path into a list, you need to reconstruct file path).
By the way, for you purpose here, there is no need to declare an empty list first (i.e. inF = [])
For unzip file part, you can do it by os.system, but I also recommend to use subprocess module instead of os.system, you will find the reason in the doc of subprocess.
DO NOT see the following code, ONLY see them after you really can not solve this by yourself.
import os
import glob
inF = glob.glob('~/TargetData/zip/*.tar.gz')
if inF:
for files in inF:
# consider subprocess.call() instead of os.system
unzip_name = files.replace('zip', 'unzip')[:-7]
# get directory name and make sure it exists, otherwise create it
unzip_dir = os.path.dirname(unzip_name)
if not os.path.exists(unzip_dir):
os.mkdir(unzip_dir)
subprocess.call(['tar -xzf', files, '-C', unzip_name])
# os.system('tar -czf files /unzip/files[:-7]')

vim complete() with result from lvim

I am trying to create a function that will pop up a list of file includes the word "Module"(case insensitive).
I tried :lvim /Module/gj *.f90 when all *.f90 is in current dir, but I failed to make a globpath() like expand so that I can include and subdirs.
So, I turned to python. From python, I am getting the list perfectly. I am inserting the python code, which will possibly show my goal:
#!/usr/bin/python
import os
import re
flsts = []
path = "/home/rudra/Devel/dream/"
print("All files==>")
for dirs, subdirs, files in os.walk(path):
for tfile in files:
if tfile.endswith('f90'):
print(os.path.splitext(tfile)[0])
text = open(dirs+'/'+tfile).read()
match = re.search("Module", text)
if match:
flsts.append(os.path.splitext(tfile)[0])
print("The list to be used ==>")
print(flsts)
after having the list, I want a
complete(col('.')), flsts)
The problem is, I am unable to include it inside vim function.
May I kindly have some help, so that I can get a list from vim and use it in the complete function?
I have checked this as a possible solution, but unfortunately it is not.
Kindly help.
edit: More explanation
So, say, in my work-dir, i have:
$tree */*.f90
OLD/dirac.f90
OLD/environment.f90
src/constants.f90
src/gencrystal.f90
src/geninp.f90
src/init.f90
among them, only two has word module in it:
$ grep Module */*.f90
OLD/dirac.f90: 10 :module mdirac
src/constants.f90: 2 :module constants
So, I want, with a inoremap, complete() to pop up only constants and dirac.
Hence, Module is the keyword I am searching in the subdirs of present working directory, and only those file matches (dirac and constants in this example) should pop up in complete()
I'm not sure what your exact problem is.
With split(globpath('./**/Module/**', '*.f90'), '\n') you will obtain the list of all files that match *.f90, and which are somewhere within a directory named Module.
Then, using complete() has a few restrictions. It has to be from a function that will be called from insert mode, and that returns an empty string.
By itself, complete() will insert the selected text, if we play with the {starcol} parameter, we can even remove what's before the cursor. This way, you can type Module, hit the key you want and use Module to filter.
function! s:Complete()
" From lh-vim-lib: word_tools.vim
let key = GetCurrentKeyword()
let files = split(glob('./**/*'.key.'*/**', '*.vim'), '\n')
call complete(col('.')-len(key), files )
return ''
endfunction
inoremap µ <c-R>=<sid>Complete()<cr>
However, if you want to trigger an action (instead of inserting text), it becomes much more complex. I did that in muTemplate. I've published the framework used to associate hooks to completion items in lh-vim-lib (See lh#icomplete#*() functions).
EDIT: OK, then, I'll work with let files=split(system("grep --include=*.f90 -Ril module *"), '\n') to obtain the list of files, then call complete(col('.'), files) with that list. That should be the more efficient solution. This is somehow quite similar to Ingo's solution. The difference is that we don't need Python if grep is available.
Regarding Python integration, well it's possible with :py vim.command(). See for instance jira-complete that integrates complete() with a Python script that builds the completion-list: https://github.com/mnpk/vim-jira-complete/blob/master/autoload/jira.vim#L116
Notes:
if "module:" can be pre-searched with ctags, it will to possible to extract your files from tags database with taglist().
It's also possible to fill dynamically the list of files with complete_add(), which is something that would make sense from a python script that tests each file one after the other.
There's an example at :help complete() that you can adapt. If you modify your Python script to output just the (newline-separated) files, you can invoke it via system():
inoremap <F5> <C-R>=FindFiles()<CR>
function! FindFiles()
call complete(col('.'), split(system('python path/to/script.py'), '\n'))
return ''
endfunction

Running bash scripts within newly created folders based on file names

I'm not sure even where to start.
I have a list of output files from a program, lets call them foo. They are numbered outputs like foo_1.out
I'd like to make a directory for each file, move the file to its directory, run a bash script within that directory, take the output from each script, copy it to the root directory as a concatenated single file.
I understand that this is not a forum for "hey, do my work for me", I'm honestly trying to learn. Any suggestions on where to look are sincerely appreciated!
Thanks!
You should probably look up the documentation for the python modules os - specifically os.path and a couple of others - and subprocess which can be found here and here respectively.
Without wanting to do it all for you as you stated - you'll be wanting to do something like:
for f in filelist:
[pth, ext] = os.path.splitext(f)
os.mkdir(pth)
out = subprocess.Popen(SCRIPTNAME, stdout=...)
# and so on...
To get a list of all files in a directory or make folders, check out the os module. Specifically, try os.listdir and os.mkdir
To copy files, you could either manually open each file, copy the contents to a string, and rewrite it to a different file. Alternatively, look at the shutil module
To run bash scripts, use the subprocess library.
All three of those should be a part of python's standard library.

Use python tarfile add without normpath being applied to arcname

I'm using python's tarfile library to create a gzipped tar file.
The tar file needs to have absolute pathnames for reasons that I've got no control over. (I'm aware that this isn't normal practice.)
When I call
tarobject.add("/foo/xx1", "/bar/xx1")
the arcname argument "/bar/xx1" is run through os.path.normpath() and converted to "bar/xx1"
How do I avoid this and end up with "/bar/xx1" as I require?
I've read that I can replace normpath somewhere, but I'm fairly new to Python and I'm not sure how to do this or what the wider implications would be.
edit
After looking at this question I had a closer look at the tarinfo object, and this seems to work:
my_tarinfo = tarobject.gettarinfo("/foo/xx1")
my_tarinfo.name = "/bar/xx1"
tarobject.addfile(my_tarinfo, file("/foo/xx1"))
You really do strange things. You need to copy /usr/lib64/python/tarfile.py to a directory in your PYTHONPATH. Then you can modify this file. But you need to bundle you own tarfile module with your code.

Categories