You can use meta_query parameter (and Query all posts where a meta key does not exist) to limit the query to only posts that have or don’t have a certain meta value.
$query = new WP_Query(array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'your_meta_key',
'compare' => 'NOT EXISTS',
),
),
'no_found_rows' => true,
'fields' => 'ids',
));
if ( $query->posts ) {
array_walk(
$query->posts,
function($post_id, $index) {
update_post_meta( $post_id, 'your_meta_key', 'meta_value' );
}
);
}
Also, depending on your hosting, you may want to set a limit to the posts_per_page
and run the script multiple times (cronjob maybe?) instead of using -1 as the query for thousands of posts might crash the site or the execution time could run out.