Copy a file to a new location and increment filename, python - python

I am trying to:
Loop through a bunch of files
makes some changes
Copy the old file to a sub directory. Here's the kicker I don't want to overwrite the file in the new directory if it already exists. (e.g. if "Filename.mxd" already exists, then copy and rename to "Filename_1.mxd". If "Filename_1.mxd" exists, then copy the file as "Filename_2.mxd" and so on...)
save the file (but do a save, not a save as so that it overwrites the existing file)
it goes something like this:
for filename in glob.glob(os.path.join(folderPath, "*.mxd")):
fullpath = os.path.join(folderPath, filename)
mxd = arcpy.mapping.MapDocument(filename)
if os.path.isfile(fullpath):
basename, filename2 = os.path.split(fullpath)
# Make some changes to my file here
# Copy the in memory file to a new location. If the file name already exists, then rename the file with the next instance of i (e.g. filename + "_" + i)
for i in range(50):
if i > 0:
print "Test1"
if arcpy.Exists(draftloc + "\\" + filename2) or arcpy.Exists(draftloc + "\\" + shortname + "_" + str(i) + extension):
print "Test2"
pass
else:
print "Test3"
arcpy.Copy_management(filename2, draftloc + "\\" + shortname + "_" + str(i) + extension)
mxd.save()
So, 2 things I decided to do, was to just set the range of files well beyond what I expect to ever occur (50). I'm sure there's a better way of doing this, by just incrementing to the next number without setting a range.
The second thing, as you may see, is that the script saves everything in the range. I just want to save it once on the next instance of i that does not occur.
Hope this makes sense,
Mike

Use a while loop instead of a for loop. Use the while loop to find the appropriate i, and then save afterwards.
The code/pseudocode would look like:
result_name = original name
i = 0
while arcpy.Exists(result_name):
i+=1
result_name = draftloc + "\\" + shortname + "_" + str(i) + extension
save as result_name
This should fix both issues.

thanks to Maty suggestion above, I've come up with my answer. For those who are interested, my code is:
result_name = filename2
print result_name
i = 0
# Check if file exists
if arcpy.Exists(draftloc + "\\" + result_name):
# If it does, increment i by 1
i+=1
# While each successive filename (including i) does not exists, then save the next filename
while not arcpy.Exists(draftloc + "\\" + shortname + "_" + str(i) + extension):
mxd.saveACopy(draftloc + "\\" + shortname + "_" + str(i) + extension)
# else if the original file didn't satisfy the if, the save it.
else:
mxd.saveACopy(draftloc + "\\" + result_name)

Related

Optimize the performance of retreiving file sizes with pysftp

I have a requirement to get the file details for certain locations (within the system and SFTP) and get the file size for some locations on SFTP which can be achieved using the shared code.
def getFileDetails(location: str):
filenames: list = []
if location.find(":") != -1:
for file in glob.glob(location):
filenames.append(getFileNameFromFilePath(file))
else:
with pysftp.Connection(host=myHostname, username=myUsername, password=myPassword) as sftp:
remote_files = [x.filename for x in sorted(sftp.listdir_attr(location), key=lambda f: f.st_mtime)]
if location == LOCATION_SFTP_A:
for filename in remote_files:
filenames.append(filename)
sftp_archive_d_size_mapping[filename] = sftp.stat(location + "/" + filename).st_size
elif location == LOCATION_SFTP_B:
for filename in remote_files:
filenames.append(filename)
sftp_archive_e_size_mapping[filename] = sftp.stat(location + "/" + filename).st_size
else:
for filename in remote_files:
filenames.append(filename)
sftp.close()
return filenames
There are more than 10000+ files in LOCATION_SFTP_A and LOCATION_SFTP_B. For each file, I need to get the file size. To get the size I am using
sftp_archive_d_size_mapping[filename] = sftp.stat(location + "/" + filename).st_size
sftp_archive_e_size_mapping[filename] = sftp.stat(location + "/" + filename).st_size
# Time Taken : 5 min+
sftp_archive_d_size_mapping[filename] = 1 #sftp.stat(location + "/" + filename).st_size
sftp_archive_e_size_mapping[filename] = 1 #sftp.stat(location + "/" + filename).st_size
# Time Taken : 20-30 s
If I comment sftp.stat(location + "/" + filename).st_size and assign static value It takes only 20-30 seconds to run the entire code. I am looking for a way How can optimize the time and get the file size details.
The Connection.listdir_attr already gives you the file size in SFTPAttributes.st_size.
There's no need to call Connection.stat for each file to get the size (again).
See also:
With pysftp or Paramiko, how can I get a directory listing complete with attributes?
How to fetch sizes of all SFTP files in a directory through Paramiko

Python - Path/Folder/File creation

I am running the following block of code to create the path to a new file:
# Opens/create the file that will be created
device_name = target_device["host"].split('.')
path = "/home/user/test_scripts/configs/" + device_name[-1] + "/"
print(path)
# Check if path exists
if not os.path.exists(path):
os.makedirs(path)
# file = open(time_now + "_" + target_device["host"] + "_config.txt", "w")
file = open(path + time_now + "_" + device_name[0] + "_config.txt", "w")
# Time Stamp File
file.write('\n Create on ' + now.strftime("%Y-%m-%d") +
' at ' + now.strftime("%H:%M:%S") + ' GMT\n')
# Writes output to file
file.write(output)
# Close file
file.close()
The code run as intended with the exception that it creates and saves the files on the directory: /home/user/test_scripts/configs/ instead on the indented one that should be: /home/user/test_scripts/configs/device_name[-1]/.
Please advise.
Regards,
./daq
Try using os.path.join(base_path, new_path) [Reference] instead of string concatenation. For example:
path = os.path.join("/home/user/test_scripts/configs/", device_name[-1])
os.makedirs(path, exist_ok=True)
new_name = time_now + "_" + device_name[0] + "_config.txt"
with open(os.path.join(path, new_name), "w+") as file:
file.write("something")
Although I don't get why you're creating a directory with device_name[-1] and as a file name using device_name[0].

Rename a file that already exists

I'm learning python and also english. And I have a problem that might be easy, but I can't solve it. I have a folder of .txt's, I was able to extract by regular expression a sequence of numbers of each one. I rename each file with the sequence I extracted from .txt
path_txt = (r'''C:\Users\user\Desktop\Doc_Classifier\TXT''')
for TXT in name_files3:
with open(path_txt + '\\' + TXT, "r") as content:
search = re.search(r'(([0-9]{4})(/)(([1][9][0-9][0-9])|([2][0-9][0-9][0-9])))', content.read())
if search is not None:
name3 = search.group(0)
name3 = name3.replace("/", "")
os.rename(os.path.join(path_txt, TXT),
os.path.join("Processos3", name3 + "_" + str(random.randint(100, 999)) + ".txt"))
I need to check if the file already exists, and rename it by adding an increment. Currently to differentiate the files I am adding a random number to the name (random.randint(100, 999))
PS: Currently the script finds "7526/2016" in .txt, by regular expression. Remove the "/". Rename the file with "75262016" + a random number (example: 7526016_111). Instead of renaming using a random number, I would like to check if the file already exists, and rename it using an increment (example: 7526016_copy1, 7526016_copy2)
Replace:
os.rename(
os.path.join(path_txt, TXT),
os.path.join("Processos3", name3 + "_" + str(random.randint(100, 999)) + ".txt")
)
With:
fp = os.path.join("Processos3", name3 + "_%d.txt")
postfix = 0
while os.path.exists(fp % postfix):
postfix += 1
os.rename(
os.path.join(path_txt, TXT),
fp % postfix
)
The code below iterates through the files found in the current working directory, and looks a base filename and for its increments. As soon as it finds an unused increment, it opens a file with that name and writes to it. So if you already have the files "foo.txt", "foo1.txt", and "foo2.txt", the code will make a new file named "foo3.txt".
import os
filenames = os.listdir()
our_filename = "foo"
cur = 0
cur_filename = "foo"
extension = ".txt"
while(True):
if (cur_filename) in filenames:
cur += 1
cur_filename = our_filename + str(cur) + extension
else:
# found a filename that doesn't exist
f = open(cur_filename,'w')
f.write(stuff)
f.close()

rename file that already exists [duplicate]

I'm learning python and also english. And I have a problem that might be easy, but I can't solve it. I have a folder of .txt's, I was able to extract by regular expression a sequence of numbers of each one. I rename each file with the sequence I extracted from .txt
path_txt = (r'''C:\Users\user\Desktop\Doc_Classifier\TXT''')
for TXT in name_files3:
with open(path_txt + '\\' + TXT, "r") as content:
search = re.search(r'(([0-9]{4})(/)(([1][9][0-9][0-9])|([2][0-9][0-9][0-9])))', content.read())
if search is not None:
name3 = search.group(0)
name3 = name3.replace("/", "")
os.rename(os.path.join(path_txt, TXT),
os.path.join("Processos3", name3 + "_" + str(random.randint(100, 999)) + ".txt"))
I need to check if the file already exists, and rename it by adding an increment. Currently to differentiate the files I am adding a random number to the name (random.randint(100, 999))
PS: Currently the script finds "7526/2016" in .txt, by regular expression. Remove the "/". Rename the file with "75262016" + a random number (example: 7526016_111). Instead of renaming using a random number, I would like to check if the file already exists, and rename it using an increment (example: 7526016_copy1, 7526016_copy2)
Replace:
os.rename(
os.path.join(path_txt, TXT),
os.path.join("Processos3", name3 + "_" + str(random.randint(100, 999)) + ".txt")
)
With:
fp = os.path.join("Processos3", name3 + "_%d.txt")
postfix = 0
while os.path.exists(fp % postfix):
postfix += 1
os.rename(
os.path.join(path_txt, TXT),
fp % postfix
)
The code below iterates through the files found in the current working directory, and looks a base filename and for its increments. As soon as it finds an unused increment, it opens a file with that name and writes to it. So if you already have the files "foo.txt", "foo1.txt", and "foo2.txt", the code will make a new file named "foo3.txt".
import os
filenames = os.listdir()
our_filename = "foo"
cur = 0
cur_filename = "foo"
extension = ".txt"
while(True):
if (cur_filename) in filenames:
cur += 1
cur_filename = our_filename + str(cur) + extension
else:
# found a filename that doesn't exist
f = open(cur_filename,'w')
f.write(stuff)
f.close()

Increment file name while writing file in Python

My code works and increments filename but only for two first files, after that it creates new strings in existing second file. Please help me upgrade code to increment go further.
text = 'some text'
file_path = '/path/to/file'
filename = 'textfile'
i = 1
txtfile = self.file_path + filename + str(i) + '.txt'
if not os.path.exists(txtfile):
text_file = open(txtfile, "a")
text_file.write(self.text)
text_file.close()
elif os.path.exists(txtfile) and i >= 1:
i += 1
text_file1 = open(self.file_path + filename + str(i) + '.txt', "a")
text_file1.write(self.text)
text_file1.close()
If your example is part of a loop, your resetting i to 1 in every iteration. Put the i=1 outside of this part.
And it will also start at 1 when you restart your program - sometimes not what you want.

Categories