diff --git a/exec.c b/exec.c
index 660d5dab1..dbda6cbb0 100644
--- a/exec.c
+++ b/exec.c
@@ -52,10 +52,17 @@
    file descriptor redirection error message
 */
 #define FD_ERROR   _( L"An error occurred while redirecting file descriptor %d" )
+
 /**
    file redirection error message
 */
 #define FILE_ERROR _( L"An error occurred while redirecting file '%ls'" )
+
+/**
+   file redirection clobbering error message
+*/
+#define NOCLOB_ERROR _( L"The file '%ls' already exists" )
+
 /**
    fork error message
 */
@@ -113,10 +120,10 @@ void exec_close( int fd )
 			if( n == fd )
 			{
 				al_set_long( open_fds,
-							 i,
-							 al_get_long( open_fds, al_get_count( open_fds ) -1 ) );
+					     i,
+					     al_get_long( open_fds, al_get_count( open_fds ) -1 ) );
 				al_truncate( open_fds, 
-							 al_get_count( open_fds ) -1 );
+					     al_get_count( open_fds ) -1 );
 				break;
 			}
 		}
@@ -288,13 +295,24 @@ static int handle_child_io( io_data_t *io )
 			case IO_FILE:
 			{
 				if( (tmp=wopen( io->param1.filename,
-                                io->param2.flags, OPEN_MASK ) )==-1 )
+						io->param2.flags, OPEN_MASK ) )==-1 )
 				{
-					debug( 1, 
-						   FILE_ERROR,
-						   io->param1.filename );
+					if( ( io->param2.flags & O_EXCL ) &&
+					    ( errno ==EEXIST ) )
+					{
+						debug( 1, 
+						       NOCLOB_ERROR,
+						       io->param1.filename );
+					}
+					else
+					{
+						debug( 1, 
+						       FILE_ERROR,
+						       io->param1.filename );
+										
+						wperror( L"open" );
+					}
 					
-					wperror( L"open" );
 					return -1;
 				}
 				else if( tmp != io->fd)
diff --git a/highlight.c b/highlight.c
index 603d75b90..8a5f75120 100644
--- a/highlight.c
+++ b/highlight.c
@@ -757,6 +757,7 @@ void highlight_shell( wchar_t * buff,
 				break;
 			}
 		
+			case TOK_REDIRECT_NOCLOB:
 			case TOK_REDIRECT_OUT:
 			case TOK_REDIRECT_IN:
 			case TOK_REDIRECT_APPEND:
@@ -825,7 +826,7 @@ void highlight_shell( wchar_t * buff,
 					  if it exists.
 					*/
 					if( last_type == TOK_REDIRECT_IN || 
-						last_type == TOK_REDIRECT_APPEND )
+					    last_type == TOK_REDIRECT_APPEND )
 					{
 						if( wstat( target, &buff ) == -1 )
 						{
@@ -834,6 +835,15 @@ void highlight_shell( wchar_t * buff,
 								al_push( error, wcsdupcat( L"File \'", target, L"\' does not exist" ) );
 						}
 					}
+					if( last_type == TOK_REDIRECT_NOCLOB )
+					{
+						if( wstat( target, &buff ) != -1 )
+						{
+							color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
+							if( error )
+								al_push( error, wcsdupcat( L"File \'", target, L"\' exists" ) );
+						}
+					}
 				}
 				break;
 			}
diff --git a/parser.c b/parser.c
index a699219e3..916dd79b7 100644
--- a/parser.c
+++ b/parser.c
@@ -1462,6 +1462,7 @@ static void parse_job_argument_list( process_t *p,
 			case TOK_REDIRECT_IN:
 			case TOK_REDIRECT_APPEND:
 			case TOK_REDIRECT_FD:
+			case TOK_REDIRECT_NOCLOB:
 			{
 				int type = tok_last_type( tok );
 				io_data_t *new_io;
@@ -1557,6 +1558,12 @@ static void parse_job_argument_list( process_t *p,
 								new_io->param1.filename = target;
 								break;
 
+							case TOK_REDIRECT_NOCLOB:
+								new_io->io_mode = IO_FILE;
+								new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY;
+								new_io->param1.filename = target;
+								break;
+
 							case TOK_REDIRECT_IN:
 								new_io->io_mode = IO_FILE;
 								new_io->param2.flags = O_RDONLY;
@@ -2121,6 +2128,7 @@ static int parse_job( process_t *p,
 							break;
 						
 						case TOK_REDIRECT_OUT:
+						case TOK_REDIRECT_NOCLOB:
 						case TOK_REDIRECT_APPEND:
 						case TOK_REDIRECT_IN:
 						case TOK_REDIRECT_FD:
@@ -3324,6 +3332,7 @@ int parser_test( const  wchar_t * buff,
 			case TOK_REDIRECT_IN:
 			case TOK_REDIRECT_APPEND:
 			case TOK_REDIRECT_FD:
+			case TOK_REDIRECT_NOCLOB:
 			{
 				if( !had_cmd )
 				{
diff --git a/tokenizer.c b/tokenizer.c
index 0551bb176..edefc070c 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -69,6 +69,7 @@ static const wchar_t *tok_desc[] =
 	N_( L"Append output to file" ),
 	N_( L"Redirect input to file" ),
 	N_( L"Redirect to file descriptor" ),
+	N_( L"Redirect output to file if file does not exist" ),
 	N_( L"Run job in background" ),
 	N_( L"Comment" )
 }
@@ -473,6 +474,11 @@ static void read_redirect( tokenizer *tok, int fd )
 		tok->buff++;
 		tok->last_type = TOK_REDIRECT_FD;
 	}
+	else if( *tok->buff == L'?' )
+	{
+		tok->buff++;
+		tok->last_type = TOK_REDIRECT_NOCLOB;
+	}
 	else
 	{
 		tok->last_type = TOK_REDIRECT_OUT + mode;
diff --git a/tokenizer.h b/tokenizer.h
index bced30e5e..3954cc481 100644
--- a/tokenizer.h
+++ b/tokenizer.h
@@ -26,6 +26,7 @@ enum token_type
 	TOK_REDIRECT_APPEND,/**< redirection append token */
 	TOK_REDIRECT_IN,/**< input redirection token */
 	TOK_REDIRECT_FD,/**< redirection to new fd token */
+	TOK_REDIRECT_NOCLOB, /**<? redirection token */
 	TOK_BACKGROUND,/**< send job to bg token */
 	TOK_COMMENT/**< comment token */
 }