subroutine class_copy(set,line,error,user_function)
  use gbl_message
  use gkernel_types
  use classcore_dependencies_interfaces
  use classcore_interfaces, except_this=>class_copy
  use class_index
  use class_common
  use class_types
  !---------------------------------------------------------------------
  ! @ public
  ! CLASS support routine for command
  !   COPY
  ! 1    [/SORTED]
  !---------------------------------------------------------------------
  type(class_setup_t), intent(in)    :: set            !
  character(len=*),    intent(in)    :: line           ! Command line
  logical,             intent(inout) :: error          ! Logical error flag
  logical,             external      :: user_function  !
  ! Local
  character(len=*), parameter :: rname='COPY'
  character(len=message_length) :: mess
  integer(kind=entry_length) :: ientry,nentry
  type(observation) :: obs
  type(time_t) :: time
  !
  ! Parse input line for /SORTED option
  if (.not.sic_present(1,0)) then
     if (set%sort_name.ne."NONE") then
        write(mess,*) 'Copying a sorted index often is inefficient'
        call class_message(seve%e,rname,mess)
        write(mess,*) 'Reform the index with SET SORT NONE or confirm the sorting with the /SORTED option'
        call class_message(seve%e,rname,mess)
        error = .true.
        return
     endif
  endif
  !
  ! Sanity checks: I. Files
  if (.not.filein_opened(rname,error))  return
  if (.not.fileout_opened(rname,error))  return
  if (filein_is_fileout()) then
     call class_message(seve%w,rname,'Input file = output file => Nothing to be done')
     return
  endif
  !
  ! Sanity checks: II. Index
  if (cx%next.le.1) then
     call class_message(seve%e,rname,'Index is empty')
     error = .true.
     return
  endif
  !
  call init_obs(obs)
  !
  ! Get number of entries in index
  nentry = cx%next-1
  !
  call gtime_init(time,nentry,error)
  if (error)  return
  !
  ! Loop on entries
  do ientry=1,nentry
    call gtime_current(time)
    !
    ! Exit when asked by user
    call class_controlc(rname,error)
    if (error)  exit
    !
    ! Read header and data sections into obs buffer from input file
    call get_it(set,obs,cx%ind(ientry),user_function,error)
    if (error)  exit
    !
    ! Output file is multiple: keep the observation number. If same
    !        number already exists, a new version will be written.
    ! Output file is single: set obs number to 0, class_write() will
    !        assign a new one automatically.
    if (fileout%desc%single)  obs%head%gen%num = 0
    !
    ! Write header and data sections from obs buffer to output file
    call class_write(set,obs,error,user_function)
    if (error)  exit
    !
  enddo
  !
  if (error) then
    write (mess,'(A,I0,A,I0,A)')  &
      'Incomplete output (stopped at ',ientry,'-th observation over ',  &
      nentry,' in index)'
    call class_message(seve%e,rname,mess)
  endif
  !
  call free_obs(obs)  ! MUST be done
  !
  call classcore_fileout_flush(error)
  !
end subroutine class_copy
