Title: copy_dir
Published: April 25, 2014
Last modified: April 28, 2025

---

# copy_dir( string $from, string $to, string[] $skip_list = array() ): true|󠀁[WP_Error](https://developer.wordpress.org/reference/classes/wp_error/)󠁿

## In this article

 * [Description](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#description)
 * [Parameters](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#source)
 * [Related](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#changelog)
 * [User Contributed Notes](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#user-contributed-notes)

[ Back to top](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#wp--skip-link--target)

Copies a directory from one location to another via the WordPress Filesystem Abstraction.

## 󠀁[Description](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#description)󠁿

Assumes that [WP_Filesystem()](https://developer.wordpress.org/reference/functions/wp_filesystem/)
has already been called and setup.

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#parameters)󠁿

 `$from`stringrequired

Source directory.

`$to`stringrequired

Destination directory.

`$skip_list`string[]optional

An array of files/folders to skip copying.

Default:`array()`

## 󠀁[Return](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#return)󠁿

 true|[WP_Error](https://developer.wordpress.org/reference/classes/wp_error/) True
on success, [WP_Error](https://developer.wordpress.org/reference/classes/wp_error/)
on failure.

## 󠀁[Source](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#source)󠁿

    ```php
    function copy_dir( $from, $to, $skip_list = array() ) {
    	global $wp_filesystem;

    	$dirlist = $wp_filesystem->dirlist( $from );

    	if ( false === $dirlist ) {
    		return new WP_Error( 'dirlist_failed_copy_dir', __( 'Directory listing failed.' ), basename( $from ) );
    	}

    	$from = trailingslashit( $from );
    	$to   = trailingslashit( $to );

    	if ( ! $wp_filesystem->exists( $to ) && ! $wp_filesystem->mkdir( $to ) ) {
    		return new WP_Error(
    			'mkdir_destination_failed_copy_dir',
    			__( 'Could not create the destination directory.' ),
    			basename( $to )
    		);
    	}

    	foreach ( (array) $dirlist as $filename => $fileinfo ) {
    		if ( in_array( $filename, $skip_list, true ) ) {
    			continue;
    		}

    		if ( 'f' === $fileinfo['type'] ) {
    			if ( ! $wp_filesystem->copy( $from . $filename, $to . $filename, true, FS_CHMOD_FILE ) ) {
    				// If copy failed, chmod file to 0644 and try again.
    				$wp_filesystem->chmod( $to . $filename, FS_CHMOD_FILE );

    				if ( ! $wp_filesystem->copy( $from . $filename, $to . $filename, true, FS_CHMOD_FILE ) ) {
    					return new WP_Error( 'copy_failed_copy_dir', __( 'Could not copy file.' ), $to . $filename );
    				}
    			}

    			wp_opcache_invalidate( $to . $filename );
    		} elseif ( 'd' === $fileinfo['type'] ) {
    			if ( ! $wp_filesystem->is_dir( $to . $filename ) ) {
    				if ( ! $wp_filesystem->mkdir( $to . $filename, FS_CHMOD_DIR ) ) {
    					return new WP_Error( 'mkdir_failed_copy_dir', __( 'Could not create directory.' ), $to . $filename );
    				}
    			}

    			// Generate the $sub_skip_list for the subdirectory as a sub-set of the existing $skip_list.
    			$sub_skip_list = array();

    			foreach ( $skip_list as $skip_item ) {
    				if ( str_starts_with( $skip_item, $filename . '/' ) ) {
    					$sub_skip_list[] = preg_replace( '!^' . preg_quote( $filename, '!' ) . '/!i', '', $skip_item );
    				}
    			}

    			$result = copy_dir( $from . $filename, $to . $filename, $sub_skip_list );

    			if ( is_wp_error( $result ) ) {
    				return $result;
    			}
    		}
    	}

    	return true;
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-admin/includes/file.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-admin/includes/file.php#L2012)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-admin/includes/file.php#L2012-L2073)

## 󠀁[Related](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#related)󠁿

| Uses | Description | 
| [wp_opcache_invalidate()](https://developer.wordpress.org/reference/functions/wp_opcache_invalidate/)`wp-admin/includes/file.php` |

Attempts to clear the opcode cache for an individual PHP file.

  | 
| [copy_dir()](https://developer.wordpress.org/reference/functions/copy_dir/)`wp-admin/includes/file.php` |

Copies a directory from one location to another via the WordPress Filesystem Abstraction.

  | 
| [__()](https://developer.wordpress.org/reference/functions/__/)`wp-includes/l10n.php` |

Retrieves the translation of $text.

  | 
| [trailingslashit()](https://developer.wordpress.org/reference/functions/trailingslashit/)`wp-includes/formatting.php` |

Appends a trailing slash.

  | 
| [is_wp_error()](https://developer.wordpress.org/reference/functions/is_wp_error/)`wp-includes/load.php` |

Checks whether the given variable is a WordPress Error.

  | 
| [WP_Error::__construct()](https://developer.wordpress.org/reference/classes/wp_error/__construct/)`wp-includes/class-wp-error.php` |

Initializes the error.

  |

[Show 4 more](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#)

| Used by | Description | 
| [move_dir()](https://developer.wordpress.org/reference/functions/move_dir/)`wp-admin/includes/file.php` |

Moves a directory from one location to another.

  | 
| [WP_Upgrader::install_package()](https://developer.wordpress.org/reference/classes/wp_upgrader/install_package/)`wp-admin/includes/class-wp-upgrader.php` |

Install a package.

  | 
| [update_core()](https://developer.wordpress.org/reference/functions/update_core/)`wp-admin/includes/update-core.php` |

Upgrades the core of WordPress.

  | 
| [copy_dir()](https://developer.wordpress.org/reference/functions/copy_dir/)`wp-admin/includes/file.php` |

Copies a directory from one location to another via the WordPress Filesystem Abstraction.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#changelog)󠁿

| Version | Description | 
| [2.5.0](https://developer.wordpress.org/reference/since/2.5.0/) | Introduced. |

## 󠀁[User Contributed Notes](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#user-contributed-notes)󠁿

 1.  [Skip to note 2 content](https://developer.wordpress.org/reference/functions/copy_dir/?output_format=md#comment-content-1815)
 2.   [J.D. Grimes](https://profiles.wordpress.org/jdgrimes/)  [  10 years ago  ](https://developer.wordpress.org/reference/functions/copy_dir/#comment-1815)
 3. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fcopy_dir%2F%23comment-1815)
    Vote results for this note: -1[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fcopy_dir%2F%23comment-1815)
 4.     ```php
        // Connecting to the filesystem.
        if ( ! WP_Filesystem() ) {
        	// Unable to connect to the filesystem, FTP credentials may be required or something.
        	// You can request these with request_filesystem_credentials()
        	exit;
        }
    
        // Don't forget that the target directory needs to exist.
        // If it doesn't already, you'll need to create it.
        global $wp_filesystem;
        $wp_filesystem->mkdir( $target_dir );
    
        // Now copy all the files in the source directory to the target directory.
        copy_dir( $src_dir, $target_dir );
        ```
    
 5.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fcopy_dir%2F%3Freplytocom%3D1815%23feedback-editor-1815)

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fcopy_dir%2F)
before being able to contribute a note or feedback.