Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
[solved] duplicate a directory or multiple files.
-
Hello there!
I've just upgraded to pynthonista3. I want to duplicate some of my old files and directories from the pythonista2 to other directories. I cant find the option in the file menu. There seem to be only 'move', and no duplicate. So how would i do that, apart from copying the content of each file one by one? (first page of forum search returned nothing relevant).
Thanks! -
-
Use
shutil.copytree
-
You can use stash cp command ("cp f1 f2 f3 destination_directory") to copy multiple files and directory. The stash command "cd ~/../Documents" would take you to top level Pythonista 2 directory. For example "ls ~/../Documents" lists the top level files in pythonista 2 directory and "ls ~/Documents" lists the top level files in pythonista 3 directory. May be you can look at the cp.py in site-packages/stash/bin to see how copy is implemented and it may help you to write your own copy command. Note that cp.py uses shutil.copytree.
-
thank you all. i did this, for anyone who needs it:
import os import shutil cwd = os.getcwd() src = '/private/var/mobile/Containers/Shared/AppGroup/blablabla/Documents/FFT' # change for the good adress dst = cwd+'/myProg1/FFT' print(src) print(dst) shutil.copytree(src,dst)
however this could be a built-in command of the editor.
-
here are two pieces of code to copy, then paste a directory:
import editor, clipboard, re, console, os '''Utilities to be added to the editor ''' def copyDirPathToClipboard(): '''Copy current file directory to the clipboard ''' # get current location file = editor.get_path() dir = os.path.dirname(file) # inform user and get confirmation msg = re.match('.*Pythonista3/Documents/(.+)',dir).group(1) ans = console.alert('Copy','Copy this directory?\n'+msg+'\nNB: select a file to get its directory!','yes') # if yes, copy to clipboard if ans == 1 : clipboard.set(dir) console.hud_alert('Done!','success',0.5) copyDirPathToClipboard()
import editor, clipboard, console, re, shutil, os '''Utility to be added to the editor ''' def pasteDir(): '''Copy the directory in clipboard to the same directory as the current file ''' # get current directory location file = editor.get_path() dir = os.path.dirname(file) # get source directory from clipboard src = clipboard.get() # get name of directory name = src.split('/') name = name[-1] # build destination name dst = dir + '/' + name # short version of destination msg = re.match('.*Pythonista3/Documents/(.+)',dst).group(1) # if already exists then cancel if os.path.exists(dst): console.alert('Paste Error','Directory:\n'+ msg + '\nalready exists! Paste not possible.') # inform user and get confirmation ans = console.alert('Paste','Create this new directory?\n'+msg,'yes') # if yes, paste if ans == 1: shutil.copytree(src,dst) console.hud_alert('Done!','success',0.5) pasteDir()
is it possible to add these in the editor wrench menu other than manually?
Thanks -
here is a set of tools that can be used for adding /removing items to the wrench menu. I have not tested this in recent versions, let me know if it does not work. You need to save the user defaults after editing.
-
thank you @JonB
your code seems ok, however i have type problems.I want to check if the action button is not already there before adding it. So i list the action.
The list of actions is, when i print it[<b'__NSCFDictionary': { arguments = paste; iconName = "Primaries_Paste"; scriptName = "/myProg1/pasteDir.py"; title = "paste_dir"; }>, <b'__NSCFDictionary': { arguments = copy; iconName = "ios7-copy-outline"; scriptName = "/myProg1/pasteDir.py"; title = "copy_dir"; }
so i create a disctionnary with title keys
lst = get_actions() titles = {} for dct in lst: titles[dct['title']] = True
but when i try to access title['copy_dir'] i get a key error.
i get when i print my dictionnary:{<b'NSTaggedPointerString': copy_dir>: True, <b'NSTaggedPointerString': paste_dir>: True}
the maybe the keys are not simple strings?
so i think i should convert my dct['title'] to strings before using them as key for the dictionnary? But i dont know how to do that, there is no tostring(). Any idea? -
use str() to convert an NSString to a python string. e.g.
str(dct['title'])
-
@JonB thanks! it does work.
Here is my final code. Nothing great here, this is just for me to get familiar with python and pythonista.
paste it where you want, run it, you should have 2 more icons in the wrench menu: copy_dir and paste_dir. There is some limited error management in these 2 function. Only problem: you must select a file in the directory (src or dst) to get the good adress, displaying the good directory is not enough.'''This script installs two utilities in the editor: copy directory paste directory Author: Jmv38 - 2016 - Pythonista3 ''' import editor, clipboard, console, re, shutil, os from sys import argv # this code is from JonB - Thank you! # source: https://github.com/jsbain/objc_hacks/blob/master/add_action.py from objc_util import * NSUserDefaults = ObjCClass('NSUserDefaults') def add_action(scriptName,iconName='python',iconColor='',title='',arguments=''): '''adds an editor action. scriptName should start with / (e.g /stash/stash.py) iconName should be an icon without leading prefix, or trailing size. i.e alert instead of iob:alert_256 iconColor should be a web style hex string, eg aa00ff title is the alternative title Call save_defaults() to store defaults ')''' defaults=NSUserDefaults.standardUserDefaults() kwargs=locals() entry={ key:kwargs[key] for key in ('scriptName','iconName','iconColor','title','arguments') if key in kwargs and kwargs[key] } editoractions=get_actions() editoractions.append(ns(entry)) defaults.setObject_forKey_(editoractions,'EditorActionInfos') def remove_action(scriptName): ''' remove all instances of a given scriptname. Call save_defaults() to store for next session ''' defaults=NSUserDefaults.standardUserDefaults() editoractions=get_actions() [editoractions.remove(x) for x in editoractions if str(x['scriptName'])==scriptName] defaults.setObject_forKey_(editoractions,'EditorActionInfos') def remove_action_at_index(index): ''' remove action at index. Call save_defaults() to save result. ''' defaults=NSUserDefaults.standardUserDefaults() editoractions = get_actions() del editoractions[index] defaults.setObject_forKey_(editoractions,'EditorActionInfos') def get_defaults_dict(): '''return NSdictionary of defaults''' defaults=NSUserDefaults.standardUserDefaults() return defaults.dictionaryRepresentation() def get_actions(): '''return action list''' defaults=NSUserDefaults.standardUserDefaults() return list(defaults.arrayForKey_('EditorActionInfos')) def save_defaults(): '''save current set of defaults''' defaults=NSUserDefaults.standardUserDefaults() NSUserDefaults.setStandardUserDefaults_(defaults) # end of JonB code def install_actions(): ''' Installs shortcuts in the wrench menu ''' # get current location file = editor.get_path() file = re.match('.+Pythonista3/Documents(/.+)',file).group(1) lst = get_actions() titles = {} for dct in lst: titles[str(dct['title'])] = True cmd = 'paste_dir' if cmd not in titles: add_action(arguments = 'paste', iconName = "Primaries_Paste", scriptName = file, title = cmd ) cmd = 'copy_dir' if cmd not in titles: add_action(arguments = 'copy', iconName = "ios7-copy-outline", scriptName = file, title = cmd ) save_defaults() def copyDir(): '''Copy current file directory to the clipboard ''' # get current location file = editor.get_path() dir = os.path.dirname(file) # inform user and get confirmation msg = re.match('.*Pythonista3/Documents/(.+)',dir).group(1) ans = console.alert('Copy', '\nNB: YOU MUST SELECT A FILE IN THE DIRECTORY TO COPY!' + '\n\nIs this the directory you want to copy?\n\n' + msg ,'yes') # if yes, copy to clipboard if ans == 1 : clipboard.set(dir) console.hud_alert('Done!','success',0.5) def pasteDir(): '''Copy the directory in clipboard to the same directory as the current file ''' # get current directory location file = editor.get_path() dir = os.path.dirname(file) # get source directory from clipboard src = clipboard.get() # is it a valid source? if not os.path.exists(src): console.alert('Paste Error', 'Directory described in clipboard does not exist! Paste not possible.' + '\nClipboard content:\n\n' + src) return msg = re.match('.+(Pythonista3/Documents/)(.+)',src) if (msg == None) or (msg.group(2) == None): msg = 'clipboard content is not a valid pythonista3 sub-directory:\n'+src+'\npaste not possible.' console.alert('Paste Error', msg) return # get name of directory name = msg.group(2) name = name.split('/')[-1] # build destination name dst = dir + '/' + name # and a short version msg = re.match('.+(Pythonista3/Documents/)(.+)',dst).group(2) # if already exists then cancel if os.path.exists(dst): console.alert('Paste Error','Directory:\n'+ msg + '\nalready exists! Paste not possible.') return # inform user and get confirmation ans = console.alert('Paste', '\nNB: YOU MUST SELECT A FILE IN THE DIRECTORY WHERE TO PASTE!' + '\n\nIs this the directory you want to create?\n\n' + msg ,'yes') # if yes, paste if ans == 1: shutil.copytree(src,dst) console.hud_alert('Done!','success',0.5) # get script argument cmd = argv[-1] if cmd == 'paste': pasteDir() elif cmd == 'copy': copyDir() else: install_actions()
-
hello @JonB.
using you code for remove_action i found a bug: not all actions were removed. This is due to the dynamic remove of the list elements. I modified your code by adding a reverse scan of the list, and now it is fixed. Thanks.def remove_action(scriptName): ''' remove all instances of a given scriptname. Call save_defaults() to store for next session ''' defaults=NSUserDefaults.standardUserDefaults() editoractions=get_actions() [editoractions.remove(x) for x in reversed(editoractions) if str(x['scriptName'])==scriptName] defaults.setObject_forKey_(editoractions,'EditorActionInfos')
-
here is the last version of code https://gist.github.com/23407f680c9744ad2beb6d1fafcca9a4
it adds 4 shortcuts: copy, paste, dir, file
remove the old shortcuts manually. -
any one who knows how to get the currently displayed editor directory without selecting a file in this directory?
Thanks! -
@jmv38 There is no way to find out what folder is currently shown in Pythonista's file list - there is no function in the
editor
orconsole
module for that. It might be possible to find this out usingobjc_util
, but I don't know Pythonista's internal structure well enough to help you with that.