diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index eafd17babdc2a831f150bc99a7c5d9da5541b293..928e050945ce7f070f6cade8a4b713191b3abeb8 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridState.GridDeviceState;
+import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
 import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice;
@@ -59,7 +60,7 @@ public final class GridContext {
     private int currentDeviceIdx = 0;
 
     private GridContext() {
-        devices.add(new DeviceAndState(null));
+        devices.add(new DeviceAndState(null, null));
     }
 
     public static GridContext getContext() {
@@ -86,10 +87,15 @@ public final class GridContext {
     }
 
     public void setCurrentDevice(String name, GridDevice currentDevice) {
+        assert !(currentDevice instanceof FileGridDevice) : "FileGridDevice must have filenamePattern";
+        setCurrentDevice(name, currentDevice, null);
+    }
+
+    public void setCurrentDevice(String name, GridDevice currentDevice, String filenamePattern) {
         RGridGraphicsAdapter.addDevice(name);
         RGridGraphicsAdapter.setCurrentDevice(name);
         currentDeviceIdx = this.devices.size();
-        this.devices.add(new DeviceAndState(currentDevice));
+        this.devices.add(new DeviceAndState(currentDevice, filenamePattern));
         assert devices.size() == RGridGraphicsAdapter.getDevicesCount();
     }
 
@@ -158,9 +164,9 @@ public final class GridContext {
         final GridDevice device;
         final GridDeviceState state;
 
-        DeviceAndState(GridDevice device) {
+        DeviceAndState(GridDevice device, String filenamePattern) {
             this.device = device;
-            this.state = new GridDeviceState();
+            this.state = new GridDeviceState(filenamePattern);
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index dac9a5976c3af8ea97a4b86fb38229cd2d6d69fd..5579a9051982fdcfa38d77d60f9ddb4a1c316fd8 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -15,6 +15,7 @@ import java.util.function.Supplier;
 
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.library.fastrGrid.grDevices.FileDevUtils;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -163,6 +164,10 @@ public final class GridState {
         return devState.scale;
     }
 
+    public String getNextPageFilename() {
+        return FileDevUtils.formatFilename(devState.filenamePattern, devState.pageIndex++);
+    }
+
     public static final class GridPalette {
         public final GridColor[] colors;
         public final String[] colorNames;
@@ -194,5 +199,11 @@ public final class GridState {
         private boolean isDisplayListOn = true;
         private RList displayList;
         private int displayListIndex = 0;
+        private int pageIndex = 2;
+        private String filenamePattern;
+
+        GridDeviceState(String filenamePattern) {
+            this.filenamePattern = filenamePattern;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 1b234eda3a3fc0e7ff305cf18785e6ec77813c36..27edec3641e8a9af72635d4db573cb0f2cc77b8f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -14,8 +14,11 @@ package com.oracle.truffle.r.library.fastrGrid;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
@@ -40,8 +43,17 @@ final class LNewPage extends RExternalBuiltinNode {
     }
 
     @TruffleBoundary
-    private static void openNewPage(GridDevice device) {
-        device.openNewPage();
+    private void openNewPage(GridDevice device) {
+        if (device instanceof FileGridDevice) {
+            String path = GridContext.getContext().getGridState().getNextPageFilename();
+            try {
+                ((FileGridDevice) device).openNewPage(path);
+            } catch (DeviceCloseException e) {
+                throw error(Message.GENERIC, "Cannot save the image. Details: " + e.getMessage());
+            }
+        } else {
+            device.openNewPage();
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/FileGridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/FileGridDevice.java
new file mode 100644
index 0000000000000000000000000000000000000000..753f4d5bfccc7d75c9e064bb0934666ba12f2af1
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/FileGridDevice.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+/**
+ * Should be implemented by devices that save their output into a file. Such devices should only
+ * accept complete filenames, i.e. without '%d' placeholder, and the handling of the placeholder is
+ * left up to the calling code.
+ */
+public interface FileGridDevice extends GridDevice {
+    /**
+     * Each call to {@link #openNewPage()} should save the current image (into the current path) and
+     * start drawing a new image into the given path, i.e. the given path becomes a new current
+     * path.
+     * 
+     * @param filename tha path where to save the next image, will not contain '%d' symbol as its
+     *            processing should be handled by the caller.
+     * @throws DeviceCloseException
+     */
+    void openNewPage(String filename) throws DeviceCloseException;
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
index 4a54283cd69ab66bf1d91d0542307e02ccae43ed..17f1667bcdae8776d5e7b9656b01aef8ce7aa277 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
@@ -39,10 +39,10 @@ import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 
-public class SVGDevice implements GridDevice {
+public class SVGDevice implements GridDevice, FileGridDevice {
     private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.000");
     private final StringBuilder data = new StringBuilder(1024);
-    private final String filename;
+    private String filename;
     private final double width;
     private final double height;
 
@@ -73,14 +73,16 @@ public class SVGDevice implements GridDevice {
                         height);
     }
 
+    @Override
+    public void openNewPage(String newFilename) throws DeviceCloseException {
+        saveFile();
+        filename = newFilename;
+        openNewPage();
+    }
+
     @Override
     public void close() throws DeviceCloseException {
-        closeSVGDocument();
-        try {
-            Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8);
-        } catch (IOException e) {
-            throw new DeviceCloseException(e);
-        }
+        saveFile();
     }
 
     @Override
@@ -181,7 +183,19 @@ public class SVGDevice implements GridDevice {
         data.append("' ").append(attributes).append(" />");
     }
 
+    private void saveFile() throws DeviceCloseException {
+        closeSVGDocument();
+        try {
+            Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            throw new DeviceCloseException(e);
+        }
+    }
+
     private void closeSVGDocument() {
+        if (data.length() == 0) {
+            return;
+        }
         if (cachedCtx != null) {
             // see #appendStyle
             append("</g>");
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
index 577784461859f69a3c600497f361c1f5b141dd17..1f95c9cfd18a2c5a0865f09be84016bacbfdf1aa 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
@@ -32,10 +32,12 @@ import java.io.IOException;
 
 import javax.imageio.ImageIO;
 
-public final class BufferedImageDevice extends Graphics2DDevice {
+import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
+
+public final class BufferedImageDevice extends Graphics2DDevice implements FileGridDevice {
     private final BufferedImage image;
-    private final String filename;
     private final String fileType;
+    private String filename;
 
     private BufferedImageDevice(String filename, String fileType, BufferedImage image, Graphics2D graphics, int width, int height) {
         super(graphics, width, height, true);
@@ -56,8 +58,19 @@ public final class BufferedImageDevice extends Graphics2DDevice {
         return new BufferedImageDevice(filename, fileType, image, graphics, width, height);
     }
 
+    @Override
+    public void openNewPage(String newFilename) throws DeviceCloseException {
+        saveImage();
+        filename = newFilename;
+        openNewPage();
+    }
+
     @Override
     public void close() throws DeviceCloseException {
+        saveImage();
+    }
+
+    private void saveImage() throws DeviceCloseException {
         try {
             ImageIO.write(image, fileType, new File(filename));
         } catch (IOException e) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
index 45bfaf37007c0f4c9f9e2c355f3b0a0086f66496..5001af1fd813ade89275b4a5ba1e9156310d3cf5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
@@ -48,7 +48,7 @@ public class DevCairo extends RExternalBuiltinNode {
             throw error(Message.INVALID_ARG_TYPE);
         }
 
-        GridContext.getContext().setCurrentDevice("svg", new SVGDevice(filename, witdh / 72., height / 72.));
+        GridContext.getContext().setCurrentDevice("svg", new SVGDevice(FileDevUtils.formatInitialFilename(filename), witdh / 72., height / 72.), filename);
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/FileDevUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/FileDevUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b3d1de5038f9fd1d407bb87c7c31690b6001b86
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/FileDevUtils.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
+
+import com.oracle.truffle.api.CompilerAsserts;
+
+public class FileDevUtils {
+    public static String formatInitialFilename(String filename) {
+        return formatFilename(filename, 1);
+    }
+
+    public static String formatFilename(String filename, int pageIndex) {
+        CompilerAsserts.neverPartOfCompilation();
+        assert filename != null;
+        assert pageIndex >= 1;
+        return String.format(filename, pageIndex);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index 49d65f69802d492b841b9a78143d565b18b3e758..de15f10dccd2b944a99a7bf02480d989c5ac3b61 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -100,8 +100,8 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
         String formatName = name.substring(0, name.indexOf("::"));
         String filename = name.substring(name.lastIndexOf(':') + 1);
         try {
-            BufferedImageDevice device = BufferedImageDevice.open(filename, formatName, width, height);
-            GridContext.getContext().setCurrentDevice(formatName.toUpperCase(), device);
+            BufferedImageDevice device = BufferedImageDevice.open(FileDevUtils.formatInitialFilename(filename), formatName, width, height);
+            GridContext.getContext().setCurrentDevice(formatName.toUpperCase(), device, filename);
         } catch (NotSupportedImageFormatException e) {
             throw error(Message.GENERIC, String.format("Format '%s' is not supported.", formatName));
         }