dcmodify(1) OFFIS DCMTK dcmodify(1)

# [NAME](#NAME)

dcmodify - Modify DICOM files

# [SYNOPSIS](#SYNOPSIS)

```
dcmodify [options] dcmfile-in...
```

# [DESCRIPTION](#DESCRIPTION)

**dcmodify** is a tool that allows one to modify, insert and delete tags and items in DICOM files. Sequences and tags with a value multiplicity &gt; 1 are also supported. Metaheader information and the tag's VR can not be modified directly by **dcmodify** at this time. In addition to tag modifications, **dcmodify** makes available some input options - forcing **dcmodify** to handle its input files as the user specifies - and output options to control the output format of the resulting files.

In case multiple modifications have to be performed, **dcmodify** does the modifications in the same order as they appear on the command line. Please note that **dcmodify** does not check whether a given value matches its value representation (VR). Usually, an error message is printed but generally the user should take care of the right VR usage.

If **dcmodify** doesn't know the tag it should insert, then the tag's VR is set to UN and the value provided on command line is interpreted as being a series of hexadecimal numbers (like they are provided for VR=OB). Please insert these tags into the dictionary to avoid this behavior. Also, specifying the *-iun* option, it is possible to force **dcmodify** to leave UN values untouched. Using option *-u* lets **dcmodify** saving all VR=UN attributes as OB.

**dcmodify** is able to work with so-called tag paths to access tags in sequences. The (pseudo-formalized) syntax is

```
{sequence[item-no].}*element
```

where 'sequence' is a sequence tag like (0008,1111) or a dictionary name for a tag. 'item-no' describes the item number to be accessed (counting from zero). 'element' defines the target tag to work on. A tag can either be specified directly as (0010,0010) or through the corresponding dictionary name 'PatientName'. The '\*' denotes that you can repeat sequence statements to access deeper levels in DICOM files (see EXAMPLES section). For 'item-no', also a wildcard character '\*' can be used selecting all items in surrounding sequence (see section WILDCARDS below).

When inserting tag paths consisting of multiple nodes (i.e. not a single element) using the *-i* option, any missing path elements (items, sequences, leaf elements) are inserted automatically when missing. That does not work for item wildcards: When no single item exists in the surrounding sequence **dcmodify** of course can't decide, how many items should be generated. However, if specifying an item number like '5', all 6 items (counted from zero) can be (and are) automatically generated in insert mode. If already 2 items would exist, the [rest (4)](/man/os/dcmtk/rest.4) would be inserted.

**dcmodify** does not work on directories, i.e. the parameter *dcmfile-in*... must not include directory names.

Please note that there are some issues concerning the modification of private tags (see PRIVATE TAGS section) and for changing UIDs (CHANGING UIDs section).

# [PARAMETERS](#PARAMETERS)

```
dcmfile-in  DICOM input filename(s) to be modified ("-" for stdin/stdout)
```

# [OPTIONS](#OPTIONS)

## [general options](#general_options)

```


  -h    --help


          print this help text and exit


        --version


          print version information and exit


        --arguments


          print expanded command line arguments


  -q    --quiet


          quiet mode, print no warnings and errors


  -v    --verbose


          verbose mode, print processing details


  -d    --debug


          debug mode, print debug information


  -ll   --log-level  [l]evel: string constant


          (fatal, error, warn, info, debug, trace)


          use level l for the logger


  -lc   --log-config  [f]ilename: string


          use config file f for the logger
```

## [input options](#input_options)

```
input file format:


  +f    --read-file


          read file format or data set (default)


  +fo   --read-file-only


          read file format only


  -f    --read-dataset


          read data set without file meta information


  +fc   --create-file


          create file format if file does not exist
input transfer syntax:


  -t=   --read-xfer-auto


          use TS recognition (default)


  -td   --read-xfer-detect


          ignore TS specified in the file meta header


  -te   --read-xfer-little


          read with explicit VR little endian TS


  -tb   --read-xfer-big


          read with explicit VR big endian TS


  -ti   --read-xfer-implicit


          read with implicit VR little endian TS
parsing of odd-length attributes:


  +ao   --accept-odd-length


          accept odd length attributes (default)


  +ae   --assume-even-length


          assume real length is one byte larger
automatic data correction:


  +dc   --enable-correction


          enable automatic data correction (default)


  -dc   --disable-correction


          disable automatic data correction
bitstream format of deflated input:


  +bd   --bitstream-deflated


          expect deflated bitstream (default)


  +bz   --bitstream-zlib


          expect deflated zlib bitstream
```

## [processing options](#processing_options)

```
backup input files:


        --backup


          backup files before modifying (default)


  -nb   --no-backup


          don't backup files (DANGEROUS)
insert mode:


  -i    --insert  "[t]ag-path=[v]alue"


          insert (or overwrite) path at position t with value v


  -if   --insert-from-file  "[t]ag-path=[f]ilename"


          insert (or overwrite) path at position t with value from file f


  -nrc  --no-reserv-check


          do not check private reservations
modify mode:


  -m    --modify  "[t]ag-path=[v]alue"


          modify tag at position t to value v


  -mf   --modify-from-file  "[t]ag-path=[f]ilename"


          modify tag at position t to value from file f


  -ma   --modify-all  "[t]ag=[v]alue"


          modify ALL matching tags t in file to value v
erase mode:


  -e    --erase  "[t]ag-path"


          erase tag/item at position t


  -ea   --erase-all  "[t]ag"


          erase ALL matching tags t in file


  -ep   --erase-private


          erase ALL private data from file
unique identifier:


  -gst  --gen-stud-uid


          generate new Study Instance UID


  -gse  --gen-ser-uid


          generate new Series Instance UID


  -gin  --gen-inst-uid


          generate new SOP Instance UID


  -nmu  --no-meta-uid


          do not update metaheader UIDs if related


          UIDs in the dataset are modified
error handling:


  -ie   --ignore-errors


          continue with file, if modify error occurs


  -imt  --ignore-missing-tags


          treat 'tag not found' as success


          when modifying or erasing in files


  -iun  --ignore-un-values


          do not try writing any values to elements


          having a VR of UN
```

## [output options](#output_options)

```
output file format:


  +F    --write-file


          write file format (default)


  -F    --write-dataset


          write data set without file meta information
output transfer syntax:


  +t=   --write-xfer-same


          write with same TS as input (default)


  +te   --write-xfer-little


          write with explicit VR little endian TS


  +tb   --write-xfer-big


          write with explicit VR big endian TS


  +ti   --write-xfer-implicit


          write with implicit VR little endian TS
post-1993 value representations:


  +u    --enable-new-vr


          enable support for new VRs (UN/UT) (default)


  -u    --disable-new-vr


          disable support for new VRs, convert to OB
group length encoding:


  +g=   --group-length-recalc


          recalculate group lengths if present (default)


  +g    --group-length-create


          always write with group length elements


  -g    --group-length-remove


          always write without group length elements
length encoding in sequences and items:


  +le   --length-explicit


          write with explicit lengths (default)


  -le   --length-undefined


          write with undefined lengths
data set trailing padding (not with --write-dataset):


  -p=   --padding-retain


          do not change padding (default if not --write-dataset)


  -p    --padding-off


          no padding (implicit if --write-dataset)


  +p    --padding-create  [f]ile-pad [i]tem-pad: integer


          align file on multiple of f bytes and items on


          multiple of i bytes
```

# [PRIVATE TAGS](#PRIVATE_TAGS)

There are some issues you have to consider when working with private tags. However, the insertion or modification of a reservation tag (gggg,00xx) should always work.

## [Insertions](#Insertions)

If you wish to insert a private tag (not a reservation with gggg,00xx), be sure, that you've listed it in your dictionary (see *&lt;docdir&gt;/datadict.txt* for details). If it's not listed, **dcmodify** will insert it with VR=UN. Also, for some cases insertion may even fail for some values.

If you've got your private tag in the dictionary, **dcmodify** acts as follows: When it finds a reservation in the tag's enclosing dataset, whose private creator matches, insertion is done with the VR found in the dictionary and the value given on command line. But if the private creator doesn't match or none is set, **dcmodify** will return with an error. If a private tag should be inserted regardless whether a reservation does not exist, the option *-nrc* can be used, forcing an insertion. However, the VR is set to UN then, because the tag then cannot be found in the dictionary.

See description above how inserting values into elements with unknown VR are handled.

## [Modifications](#Modifications)

If you modify a private tags value, **dcmodify** won't check its VR against the dictionary. So please be careful to enter only values that match the tag's VR.

If you wish to change a private tags value *and* VR, because you just added this tag to your dictionary, you can delete it with **dcmodify** and re-insert it. Then **dcmodify** uses your dictionary entry to determine the right VR (also see subsection insertions).

Also, see description above how inserting values into elements with unknown VR are handled.

## [Deletions](#Deletions)

When you use **dcmodify** to delete a private reservation tag, please note that **dcmodify** won't touch the private tags that are under this reservation. The user is forced to handle the consistency between reservations and their associated private tags.

For the deletion of private non-reservation tags there are no special issues.

# [CHANGING UIDS](#CHANGING_UIDS)

**dcmodify** will automatically correct 'Media Storage SOP Class UID' and 'Media Storage SOP Instance UID' in the metaheader, if you make changes to the related tags in the dataset ('SOP Class UID' and 'SOP Instance UID') via insert or modify mode options. You can disable this behavior by using the *-nmu* option.

If you generate new UID's with *-gst*, *-gse* or *-gin*, this will only affect the UID you chose to generate. So if you use *-gst* to generate a new 'Study Instance UID', then 'Series Instance UID' and 'SOP Instance UID' will not be affected! This gives you the possibility to generate each value separately. Normally, you would also modify the 'underlying' UIDs. As a disadvantage of this flexibility, the user has to assure, that when creating 'new' DICOM files with new UIDs with **dcmodify**, other UIDs have to be updated by the user as necessary.

When choosing the *-gin* option, the related metaheader tag ('Media Storage SOP Instance UID') is updated automatically. This behavior cannot be disabled.

When working on multiple input files, **dcmodify** processes each file in isolated fashion, i.e. it will generate UIDs for each single file. For example, when using the *-gst* option, **dcmodify** will insert a different Study Instance UID into each file instead of generating a single one and writing it to each file that is being processed.

# [CREATING NEW FILES](#CREATING_NEW_FILES)

Option *--create-file* lets **dcmodify** create a file if it does not already exist on disk. This can be used in order to create files from scratch by performing consecutive insertions with options like *--insert*. This might especially become handy when creating query files for tools like **findscu** or **movescu**. In case no specific output transfer syntax is defined, **dcmodify** chooses Little Endian Explicit Uncompressed for output. Files that are newly created are always written as DICOM file format, i.e. option *--write-dataset* is not permitted together with *--create*. This way, at least the metaheader is written and no file with zero byte length is created in a case where no insertions are performed in the **dcmodify** call.

# [ELEMENT VALUES FROM FILE](#ELEMENT_VALUES_FROM_FILE)

In order to read the element value from a file instead of specifying it on the command line, option *-mf* and *-if* can be used. Please note that for OW elements, the data is expected to be little endian ordered and will be swapped if necessary. The file size should always be an even number of bytes, i.e. no automatic padding is performed.

# [WILDCARDS](#WILDCARDS)

**dcmodify** also permits the usage of a wildcard character '\*' for item numbers in path expressions, e.g. 'ContentSequence\[\*].CodeValue' selects all 'Code Value' attributes in all items of the ContentSequence. Using a wildcard is possible for all basic operations, i.e. modifying *-m*, inserting *-i* and *-e* options which makes it, together with the automatic creation of intermediate path nodes a powerful tool for construction and processing complex datasets.

The options *-ma* and *-ea* for modifying or deleting all occurrences of a DICOM element based on its tag do not accept any wildcards but only work on single elements (i.e. a single dictionary name or tag key).

# [EXAMPLES](#EXAMPLES)

```
-i   --insert:


       dcmodify -i "(0010,0010)=A Name" file.dcm


       Inserts the PatientName tag into 'file.dcm' at 1st level.


       If tag already exists, -i will overwrite it!  If you want to


       insert an element with value multiplicity > 1 (e.g. 4) you


       can do this with: dcmodify -i "(0018,1310)=1\2\3\4"


       dcmodify -i "(0008,1111)[0].PatientName=Another Name" *.dcm


       Inserts PatientName tag into the first item of sequence


       (0008,1111).  Note that the use of wildcards for files is


       possible.  You can specify longer tag paths, too (e.g.


       "(0008,1111)[0].(0008,1111)[1].(0010,0010)=A Third One").


       If any part of the path, e.g. the sequence or the item "0"


       does not exist, it is automatically inserted by dcmodify.


       dcmodify -i "(0008,1111)[*].PatientName=Another Name" *.dcm


       Inserts PatientName tag into _every_ item of sequence


       (0008,1111).  Note that the use of wildcards for files is


       possible.  You can specify longer tag paths, too (e.g.


       "(0008,1111)[*].(0008,1111)[*].(0010,0010)=A Third One").
-if  --insert-from-file:


       dcmodify -if "PixelData=pixel.raw" file.dcm


       Inserts the content of file 'pixel.raw' into the PixelData element


       of 'file.dcm'.  The contents of the file will be read as is.


       OW data is expected to be little endian ordered and will be


       swapped if necessary.  No checks will be made to ensure that the


       amount of data is reasonable in terms of other attributes such as


       Rows or Columns.
-m   --modify:


       dcmodify -m "(0010,0010)=A Name" file.dcm


       Changes tag (0010,0010) on 1st level to "A Name".


       This option also permits longer tag paths as demonstrated above


       for -i. If the leaf element or any intermediate part of the path


       does not exist, it is not inserted as it would be if using the


       '-i' option.


       dcmodify -m "(0010,0010)=A Name" -imt file.dcm


       Changes tag (0010,0010) on 1st level to "A Name". Due to the given


       option '-imt', success is returned instead of "tag not found", if


       the element/item (or any intermediate node in a longer path) does


       not exist.


       Note that for the '-m' option the last node in the path must be a


       leaf element, i.e. not a sequence or an item.
-mf  --modify-from-file:


       dcmodify -mf "PixelData=pixel.raw" file.dcm


       Does the same as -if in case there was already a PixelData element


       in 'file.dcm'.  Otherwise nothing is changed.
-ma  --modify-all:


       dcmodify -ma "(0010,0010)=New Name" file.dcm


       Does the same as -m but works on all matching tags found in


       'file.dcm'.  Therefore, it searches the whole dataset including


       sequences for tag (0010,0010) and changes them to "New Name"
-e   --erase:


       dcmodify -e "(0010,0010)" *.dcm


       Erases tag (0010,0010) in all *.dcm files at 1st level.


       This option also allows longer tag paths as demonstrated


       above for -i.


       dcmodify -e "(0010,0010)" -imt *.dcm


       Erases tag (0010,0010) in all *.dcm files at 1st level. Due to the


       given option '-imt', success is returned instead of "tag not


       found", if the element/item (or any intermediate node in a longer


       path) does not exist.
-ea  --erase-all:


       dcmodify -ea "(0010,0010)" *.dcm


       Same as -e, but also searches in sequences and items.
-ep  --erase-private:


       dcmodify -ep *.dcm


       Deletes all private tags (i.e. tags having an odd group number)


       from all files matching *.dcm in the current directory.
-gst --gen-stud-uid:


       dcmodify -gst file.dcm


       This generates a new value for the StudyInstanceUID (0020,000d).


       Other UIDs are not modified!
-gse --gen-ser-uid:


       dcmodify -gse file.dcm


       This generates a new value for the SeriesInstanceUID (0020,000e).


       Other UIDs are not modified!
-gin --gen-inst-uid:


       dcmodify -gin file.dcm


       This command generates a new value for the SOPInstanceUID


       (0008,0018).  The corresponding MediaStorageSOPInstanceUID


       (0002,0003) is adjusted to the new value automatically.


       Please note that it's not possible to avoid this metaheader


       update via the -nmu option.
-nmu --no-meta-uid:


       dcmodify -m "SOPInstanceUID=[UID]" -nmu *.dcm


       This will modify the SOPInstanceUID to the given [UID], but -nmu


       avoids, that dcmodify adjusts the MediaStorageSOPInstanceUID in


       the metaheader, too.
```

# [ERROR HANDLING](#ERROR_HANDLING)

**dcmodify** tries executing each modify operation given on command line: If one returns an error, the others are being performed anyway. However in case of any error, the modified file is not saved, unless the *--ignore-errors* option is specified. If that option is selected, **dcmodify** also continues modifying further files specified on command line; otherwise **dcmodify** exits after the first file that had modification errors.

If the *--ignore-missing-tags* option is enabled, any modify or erase operations (i.e. not *--insert*) that fails because of a non-existing tag is treated as being successful. That does make sense if someone wants to be sure that specific tags are not present in the file or that - if they exist - that they are set to a specific value.

# [LOGGING](#LOGGING)

The level of logging output of the various command line tools and underlying libraries can be specified by the user. By default, only errors and warnings are written to the standard error stream. Using option *--verbose* also informational messages like processing details are reported. Option *--debug* can be used to get more details on the internal activity, e.g. for debugging purposes. Other logging levels can be selected using option *--log-level*. In *--quiet* mode only fatal errors are reported. In such very severe error events, the application will usually terminate. For more details on the different logging levels, see documentation of module 'oflog'.

In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option *--log-config* can be used. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated. An example configuration file is provided in *&lt;etcdir&gt;/logger.cfg*.

# [COMMAND LINE](#COMMAND_LINE)

All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values.

Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively. Usually, order and position of command line options are arbitrary (i.e. they can appear anywhere). However, if options are mutually exclusive the rightmost appearance is used. This behavior conforms to the standard evaluation rules of common Unix shells.

In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e.g. *@command.txt*). Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation. Please note that a command file cannot contain another command file. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file *&lt;datadir&gt;/dumppat.txt*).

# [ENVIRONMENT](#ENVIRONMENT)

The **dcmodify** utility will attempt to load DICOM data dictionaries specified in the *DCMDICTPATH* environment variable. By default, i.e. if the *DCMDICTPATH* environment variable is not set, the file *&lt;datadir&gt;/dicom.dic* will be loaded unless the dictionary is built into the application (default for Windows).

The default behavior should be preferred and the *DCMDICTPATH* environment variable only used when alternative data dictionaries are required. The *DCMDICTPATH* environment variable has the same format as the Unix shell *PATH* variable in that a colon (':') separates entries. On Windows systems, a semicolon (';') is used as a separator. The data dictionary code will attempt to load each file specified in the *DCMDICTPATH* environment variable. It is an error if no data dictionary can be loaded.

# [COPYRIGHT](#COPYRIGHT)

Copyright (C) 2003-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.

Mon Dec 15 2025 Version 3.7.0

---

Document: dcmodify(1) from dcmtk 3.7.0-r8 (Chainguard OS)
Source: https://github.com/DCMTK/dcmtk
