python script expected an indent block in if statement - python

I'm trying to write a basic backup script from one folder to another, and I got it to work - but the directory structure was not being copied over, just the files. I'm trying to copy in the subfolder as well, so that, for example, c:\temp\docs\file.txt goes to d:\temp\docs\file.txt instead of just d:\temp\file.txt
My issue exists in indentation with my if/else statement, but everything looks good to me. What am I doing wrong?
import datetime, time, string, os, shutil
COPY_FROM_LOCATION = 'C:\\xampp\\htdocs\\projects'
folder_date = time.strftime("%Y-%m-%d")
BACKUP_TO_LOCATION = 'D:\\BACKUP\\' + folder_date
#Create a new directory in D:\BACKUP based on today's date so the folder you're trying to copy to actually exists:
if not os.path.exists(BACKUP_TO_LOCATION):
os.makedirs(BACKUP_TO_LOCATION)
#copy function
def backup(source_folder, target_folder):
for subdir, dirs, files in os.walk(source_folder):
if subdir == source_folder :
new_target_folder = target_folder
else:
folder_name = subdir.split("C:\\xampp\\htdocs\\projects\\",1)[-1]
new_target_folder = target_folder + "\\" + folder_name
for file in files:
print "backing up: " + folder_name
shutil.copy2(os.path.join(subdir, file), new_target_folder)
backup(COPY_FROM_LOCATION,BACKUP_TO_LOCATION)
Here's the error I'm getting:
File "backup.py", line 15
new_target_folder = target_folder
^
IndentationError: expected an indented block

You're intermixing tabs and spaces.
Use one or the other, not both. Preferably spaces.

This error typically means there is an error in indentation. Check you don't mix tabs and spaces.
You can use https://www.pylint.org/ to detect them or if it something simple paste the code at http://pep8online.com, it will show you what you can enhance.

what's up with the weirdness with the space before the semi-colon? I've not seen it done that way before, that appears to be where this script is choking up.
change
if subdir == source_folder :
with
if subdir == source_folder:

Related

Creating a directory using part of a variable name

New to python and Im trying to create a set of directories, and create a file in each one, the input name will be a string starting with a > sign but I don't want the directory to contain the >.
I've tried to do the following;
seq_id = ">seq"
dirname = seq_id[1:]
print(dirname)
if not os.path.isdir('./' + dirname + '/'):
os.mkdir('./' + dirname + '/')
print("directory made")
It will not make the directory when I used the seq_id[1:] bit but it will print it. So I don't really get why it won't create the directory.
I ultimately want to build a function that would take a list of seq_ids from a file, >seq1 >seq2 >seq3 etc and create a directory for each one.
(Working with python3.5)
You must know the directories will be created at your current directory position.
If you are in folder /tmp/foo/, your script in /tmp/bar/myscript.py and you execute it with python ../bar/myscript.py the directories will be created in /tmp/foo/, not /tmp/bar/.
More of that, because you just skip possible errors with if not os.path.isdir('./' + dirname + '/'): and never prints nothing, you will not know if directory already exists.
You could do something like:
import os
strings = ['>foo', '>bar', '>baz']
def make_directories(input_list):
for string in input_list:
dirpath = os.path.join('./', string[1:])
try:
os.mkdir(dirpath)
except FileExistsError:
print('Directory {} already exists'.format(dirpath))
else:
print('Directory {} created'.format(dirpath))
make_directories(strings)
It uses os.path.join instead of homemade concatenation. It's a best practice you should always follow.
It uses try / except instead of if, again it's a best practice you should follow (Reference)
It prints things, so you know what is going on.

Spaces in directory path python

I'm a noob at coding Python and I've run into something that no amount of Googling is helping me with.
I'm trying to write a simple Directory listing tool and I cannot seem to deal with Spaces in the directory name in OSX.
My code is as follows:
def listdir_nohidden(path):
import os
for f in os.listdir(path):
if not f.startswith('.'):
yield f
def MACListDirNoExt():
import os
MACu = PCu = os.environ['USER']
MACDIR = '/Users/'+MACu+'/Desktop//'
while True:
PATH = raw_input("What is the PATH you would like to list?")
if os.path.exists(PATH):
break
else:
print "That PATH cannot be found or does not exist."
NAME = raw_input ("What would you like to name your file?")
DIR = listdir_nohidden(PATH)
DIR = [os.path.splitext(x)[0] for x in DIR]
f = open(''+MACDIR+NAME+'.txt', "w")
for file in DIR:
f.write(str(file) + "\n")
f.close()
print "The file %s.txt has been written to your Desktop" % (NAME)
raw_input ("Press Enter to exit")
For ease of trouble shooting though I think this could essentially be boiled down to:
import os
PATH = raw_input("What is the PATH you would like to list")
os.listdir(PATH)
When supplying a directory path that contains spaces /Volumes/Disk/this is a folder it returns
"No such file or Directory: '/Volumes/Disk/this\\ is\\ a\\ folder/'
It looks like its escaping the escape...?
Check the value returned from raw_input() for occurences of '\\' and replace them with ''.
a = a.replace('\\', '')
I just ran into this, and I'm guessing that what I was hastily doing is also what you were trying. In a way, both #zwol and #trans1st0r are right.
Your boiled down program has nothing wrong with it. I believe that if you put in the input /Volumes/Disk/this is a folder, everything would work fine.
However, what you may have been doing (or at least, what I was doing) is dragging a folder from the Finder to the Terminal. When you drag to the Terminal, the OS automatically escapes spaces for you, so what ends up getting typed into the Terminal is /Volumes/Disk/this\ is\ a\ folder.
So either you can make sure that what you "type in" doesn't have those backslashes, or you can use #trans1st0r's suggestion as a way to support the dragging functionality, though the latter will cause issues in the edge case that your desired path actually has backslashes in it.

Beginner Python 3--os.path and WinError2

import os
searchFolder = input('Which folder would you like to search?')
def search(folder):
for foldername, subfolders, filenames in os.walk(folder):
for filename in filenames:
if os.path.getsize(filename) > 1000:
print(str(os.path.abspath(filename)) + 'is ' + str(os.path.getsize(filename)))
else:
continue
search(searchFolder)
This program is meant to ask the user for a string, iterate over the files in that directory, and print the abs path and file size of every item over a certain size. I'm getting a FileNotFoundError: [WinError 2] when I run this code, on any directory. I'm inputting the directory with escaped backslashes. I think this is such a rudimentary error on my part that this is all the info anyone would need but let me know if there's anything else that would be helpful. Thanks!
In the filename for loop you have only passed the filename but not the complete path. If you write:
if os.path.getsize(foldername+"/"+filename) > 1000:
This works for linux. For Windows you need to use \ or \\instead of /. So now you understand why it isn't working. You should use the full filepath or relative path while adding a path.
Working code in linux:
import os
searchFolder = input('Which folder would you like to search? ')
def search(folder):
for foldername, subfolders, filenames in os.walk(folder):
for filename in filenames:
if os.path.getsize(foldername+"/"+filename) > 1000:
print(str(os.path.abspath(filename)) + ' is ' + str(os.path.getsize(foldername+"/"+filename)))
else:
continue
search(searchFolder)
Input() will return the string that the user writes. You don't have to escape backslashes. So just input it as C:\path\to\my\folder\. It's when you write windows paths in your python source code that you must escape your backslashes or use r"raw string".
You can use os.path.isdir() to check that python actually accepts the path, and print an error if the path could not be found.
searchFolder = input('Which folder would you like to search?')
if os.path.isdir(searchFolder):
search(searchFolder)
else:
print("the folder %s was not found" % searchFolder)
I tested the code and it works fine, I used for my test. ./
Python accepts both path types:
path = "C:/" # unix
and
path = "C:\\" # windows
for input try ./ , which will search the directory the program is in.
So, you have two options, relative pathing or absolute pathing.
More on pathing.
Although as was mentioned, for anything outside of the programs directory you need to correct the line
if os.path.getsize(filename) > 1000:
to
if os.path.getsize(foldername+"/"+filename) > 1000:
Whenever you want to insert any path, just add an r before the path. This is Python's raw string notation. i.e; backslashes are not handled in any special way in a string literal prefixed with r
So, if you want to add a path to a file called foo in C:\Users\pep\Documents
Just give your path as
my_path = r'C:\Users\pep\Documents\foo'
You don't need to bother escaping any backslashes now.

How does one rename multiple files using python?

I have lots of programming experience but this is my first python script. I am trying to add the prefix "00" to all the files in a specific folder. First I read the names of all the files and save them in an array. Then I sort through the array and add the prefix "00" then use the os.rename function but somewhere along the way I've messed up something.
import sys, os
file_list = []
for file in os.listdir(sys.argv[1]):
file_list.append(file)
for i in file_list:
file_list[i] = prevName
newName = '00' + file_list[i]
os.rename(prevName, newName)
I have a .py file in the folder with all the files I want to rename. The .py file contains the script above. When i double click the .py file a cmd window flashes and disappears and none of the file names have been changed. Any help would be appreciated, sorry if this is a very obvious mistake, my python level is quite n00b at the moment.
In addition to the answer by #Padraic, also make following changes to your code.
import sys, os
file_list = []
for f in os.listdir(sys.argv[1]):
file_list.append(f)
for i in range(len(file_list)):
prevName = file_list[i]
if prevName != 'stackoverflow.py': # Mention .py file so that it doesnt get renamed
newName = '00' + file_list[i]
os.rename(prevName, newName)
Check your indentation. The second for loop is not indented correctly.
for i in file_list:
file_list[i] = prevName
You are not iterating correctly. for loops in Python are like foreach loops you may know from other programming languages. i in for i in file_list actually gives you the list's elements, so you should be doing
for i in range(len(file_list)):
file_list[i] = ......
although it is not very pythonic nor generally a good idea to modify the collection that you're currently iterating over.
Your code errors because you provide no args so sys.argv[1] would give an IndexError, you would need to call the script with the dir name from a cmd prompt not double click it:
python your_script directory <- argv[1]
Or change the code and specify the path, you also need to join the path to the filename.
path = "full_path"
for f in os.listdir(path):
curr,new = os.path.join(path,f), os.path.join(path,"00{}".format(f))
os.rename(curr,new)
os.listdir returns a list so just iterate over that, you don't need to create a list and append to it.
for i in file_list: would also make each i a filename not an index so that would cause another error but as above you don't need to do it anyway.

Python: Dynamically add relative path, based on OS

I wrote my first program in Python for my dad to convert about 1000 old AppleWorks files that he has (the AppleWorks format, .cwk, is no longer supported) to .docx. To clarify, the program does not actually convert anything, all it does is copy/paste whatever text is in the documents you specify to another document of any file-type you want.
The program works fine on my Windows Laptop, however it encounters problems in my dad's Mac laptop.
File-path in Windows is indicated with a \ whereas in Mac it's /. So when the program reaches the copy and paste variables it stops working if the slash in the respective string is the wrong way around.
Is there a way to get Python to dynamically add on the Input and Output folders to my copy and paste variables depending on the OS without the use of strings?
If there are any other improvements you can see, feel free to say so, I am interested in releasing this as Freeware, possibly with the tKinter GUI and want to make as user friendly as possible.
As it stands the program does have some problems (converting apostrophe's into omega symbols and the like). Feel free to try the program and see if you can improve it.
import os, os.path
import csv
from os import listdir
import sys
import shutil
path, dirs, files = os.walk(os.getcwd() + '/Input').next()
file_count = len(files)
if file_count > 0:
print "There are " + str(file_count) + " files you have chosen to convert."
else:
print "Please put some files in the the folder labelled 'Input' to continue."
ext = raw_input("Please type the file extension you wish to convert to, making sure to preceed your selection with '.' eg. '.doc'")
convert = raw_input("You have chosen to convert " + str(file_count) + " files to the " + ext + " format. Hit 'Enter' to continue.")
if convert == "":
print "Converter is now performing selected tasks."
def main():
dirList = os.listdir(path)
for fname in dirList:
print fname
# opens files at the document_input directory.
copy = open(os.getcwd() + "\Input\\" + fname, "r")
# Make a file called test.docx and stick it in a variable called 'paste'
paste = open(os.getcwd() + "\Output\\" + fname + ext, "w+")
# Place the cursor at the beginning of 'copy'
copy.seek(0)
# Copy all the text from 'copy' to 'paste'
shutil.copyfileobj(copy,paste)
# Close both documents
copy.close()
paste.close()
if __name__=='__main__':
main()
else:
print "Huh?"
sys.exit(0)
Please let me know if I wasn't clear or left out some info...
Use os.path.join
For example, you could get the path of the Input subdirectory with
path = os.path.join(os.getcwd(), 'Input')
os.path.join is the platform-independent way to join paths:
>>> os.path.join(os.getcwd(), 'Input', fname)
'C:\\Users\\Blender\\Downloads\\Input\\foo.txt'
And on Linux:
>>> os.path.join(os.getcwd(), 'Input', fname)
'/home/blender/Downloads/Input/foo.txt'

Categories